160 lines
3.8 KiB
JavaScript
160 lines
3.8 KiB
JavaScript
const {
|
|
lstatSync,
|
|
readdirSync,
|
|
mkdirSync,
|
|
copyFileSync,
|
|
writeFileSync,
|
|
readFileSync
|
|
} = require('fs')
|
|
const {
|
|
join,
|
|
basename
|
|
} = require('path')
|
|
const includepaths = require("rollup-plugin-includepaths")
|
|
|
|
const isDirectory = source => lstatSync(source).isDirectory()
|
|
const getDirectories = source =>
|
|
readdirSync(source).map(name => join(source, name)).filter(isDirectory)
|
|
|
|
function ensureDir(folder) {
|
|
try {
|
|
if (!isDirectory(folder)) mkdirSync(folder)
|
|
} catch (e) {
|
|
mkdirSync(folder)
|
|
}
|
|
}
|
|
|
|
ensureDir("./out")
|
|
|
|
const sass = require('sass');
|
|
|
|
function findHead(elm) {
|
|
if (elm.tagName === "head") return elm;
|
|
for (let i = 0; i < elm.childNodes.length; i++) {
|
|
let res = findHead(elm.childNodes[i])
|
|
if (res) return res;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
const rollup = require("rollup")
|
|
const minify = require("html-minifier").minify
|
|
const gzipSize = require('gzip-size');
|
|
|
|
async function buildPage(folder, name) {
|
|
const pagename = basename(folder);
|
|
const outpath = "./out/" + pagename;
|
|
|
|
ensureDir(outpath)
|
|
|
|
let bundle = await rollup.rollup({
|
|
input: `${folder}/${pagename}.js`,
|
|
plugins: [includepaths({
|
|
paths: ["shared"]
|
|
})],
|
|
})
|
|
|
|
let {
|
|
code,
|
|
map
|
|
} = await bundle.generate({
|
|
format: "iife",
|
|
|
|
})
|
|
|
|
let sass_res = sass.renderSync({
|
|
file: folder + `/${pagename}.scss`,
|
|
includePaths: ["./node_modules", folder, "./shared"],
|
|
outputStyle: "compressed"
|
|
})
|
|
|
|
let css = "<style>\n" + sass_res.css.toString("utf8") + "\n</style>\n";
|
|
let script = "<script>\n" + code + "\n</script>\n";
|
|
let html = readFileSync(`${folder}/${pagename}.hbs`).toString("utf8");
|
|
|
|
let idx = html.indexOf("</head>")
|
|
if (idx < 0) throw new Error("No head element found")
|
|
let idx2 = html.indexOf("</body>")
|
|
if (idx2 < 0) throw new Error("No body element found")
|
|
|
|
if (idx < idx2) {
|
|
let part1 = html.slice(0, idx)
|
|
let part2 = html.slice(idx, idx2);
|
|
let part3 = html.slice(idx2, html.length);
|
|
html = part1 + css + part2 + script + part3;
|
|
} else {
|
|
let part1 = html.slice(0, idx2)
|
|
let part2 = html.slice(idx2, idx);
|
|
let part3 = html.slice(idx, html.length);
|
|
html = part1 + script + part2 + css + part3;
|
|
}
|
|
|
|
let result = minify(html, {
|
|
removeAttributeQuotes: true,
|
|
collapseWhitespace: true,
|
|
html5: true,
|
|
keepClosingSlash: true,
|
|
minifyCSS: true,
|
|
minifyJS: true,
|
|
removeComments: true,
|
|
useShortDoctype: true
|
|
})
|
|
|
|
let gzips = await gzipSize(result)
|
|
writeFileSync(`${outpath}/${pagename}.html`, result)
|
|
|
|
let stats = {
|
|
sass: sass_res.stats,
|
|
js: {
|
|
chars: code.length
|
|
},
|
|
css: {
|
|
chars: css.length
|
|
},
|
|
bundle_size: result.length,
|
|
gzip_size: gzips
|
|
}
|
|
|
|
writeFileSync(outpath + `/stats.json`, JSON.stringify(stats, null, " "))
|
|
}
|
|
|
|
async function run() {
|
|
const pages = getDirectories("./src");
|
|
const ProgressBar = require('progress');
|
|
// const bar = new ProgressBar('[:bar] :current/:total :percent :elapseds :etas', {
|
|
// // schema: '[:bar] :current/:total :percent :elapseds :etas',
|
|
// total: pages.length
|
|
// });
|
|
await Promise.all(pages.map(async e => {
|
|
try {
|
|
await buildPage(e)
|
|
} catch (er) {
|
|
console.error("Failed compiling", basename(e))
|
|
console.log(er.message)
|
|
}
|
|
// bar.tick()
|
|
}))
|
|
console.log("Finished compiling!")
|
|
|
|
}
|
|
|
|
|
|
if (process.argv.join(" ").toLowerCase().indexOf("watch") < 0) {
|
|
run()
|
|
} else {
|
|
const nodemon = require('nodemon');
|
|
|
|
nodemon({
|
|
script: "dummy.js",
|
|
ext: 'js hbs scss',
|
|
ignore: ["out/"]
|
|
});
|
|
|
|
nodemon.on('start', function () {
|
|
run()
|
|
}).on('quit', function () {
|
|
process.exit();
|
|
}).on('restart', function (files) {
|
|
// console.log('App restarted due to: ', files);
|
|
});
|
|
} |