Improve incremental build times
This commit is contained in:
parent
ca77149597
commit
0f5e086eba
4 changed files with 5223 additions and 174 deletions
232
client/build.js
232
client/build.js
|
@ -4,20 +4,20 @@
|
|||
// -------------------------------------------------
|
||||
|
||||
const webapp_icons = [
|
||||
{name: 'android-chrome-192x192.png', size: 192},
|
||||
{name: 'android-chrome-512x512.png', size: 512},
|
||||
{name: 'apple-touch-icon.png', size: 180},
|
||||
{name: 'mstile-150x150.png', size: 150}
|
||||
{ name: 'android-chrome-192x192.png', size: 192 },
|
||||
{ name: 'android-chrome-512x512.png', size: 512 },
|
||||
{ name: 'apple-touch-icon.png', size: 180 },
|
||||
{ name: 'mstile-150x150.png', size: 150 }
|
||||
];
|
||||
|
||||
const webapp_splash_screens = [
|
||||
{w: 640, h: 1136, center: 320},
|
||||
{w: 750, h: 1294, center: 375},
|
||||
{w: 1125, h: 2436, center: 565},
|
||||
{w: 1242, h: 2148, center: 625},
|
||||
{w: 1536, h: 2048, center: 770},
|
||||
{w: 1668, h: 2224, center: 820},
|
||||
{w: 2048, h: 2732, center: 1024}
|
||||
{ w: 640, h: 1136, center: 320 },
|
||||
{ w: 750, h: 1294, center: 375 },
|
||||
{ w: 1125, h: 2436, center: 565 },
|
||||
{ w: 1242, h: 2148, center: 625 },
|
||||
{ w: 1536, h: 2048, center: 770 },
|
||||
{ w: 1668, h: 2224, center: 820 },
|
||||
{ w: 2048, h: 2732, center: 1024 }
|
||||
];
|
||||
|
||||
const external_js = [
|
||||
|
@ -57,6 +57,8 @@ const glob = require('glob');
|
|||
const path = require('path');
|
||||
const util = require('util');
|
||||
const execSync = require('child_process').execSync;
|
||||
const browserify = require('browserify');
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
function readTextFile(path) {
|
||||
return fs.readFileSync(path, 'utf-8');
|
||||
|
@ -112,7 +114,7 @@ function bundleHtml() {
|
|||
(match, number) => { return placeholders[number]; });
|
||||
|
||||
const functionText = underscore.template(
|
||||
templateText, {variable: 'ctx'}).source;
|
||||
templateText, { variable: 'ctx' }).source;
|
||||
|
||||
compiledTemplateJs.push(`templates['${name}'] = ${functionText};`);
|
||||
}
|
||||
|
@ -131,7 +133,7 @@ function bundleCss() {
|
|||
|
||||
let css = '';
|
||||
for (const file of glob.sync('./css/**/*.styl')) {
|
||||
css += stylus.render(readTextFile(file), {filename: file});
|
||||
css += stylus.render(readTextFile(file), { filename: file });
|
||||
}
|
||||
fs.writeFileSync('./public/css/app.min.css', minifyCss(css));
|
||||
if (process.argv.includes('--gzip')) {
|
||||
|
@ -148,56 +150,64 @@ function bundleCss() {
|
|||
console.info('Bundled CSS');
|
||||
}
|
||||
|
||||
function minifyJs(path) {
|
||||
return require('terser').minify(
|
||||
fs.readFileSync(path, 'utf-8'), { compress: { unused: false } }).code;
|
||||
}
|
||||
|
||||
function writeJsBundle(b, path, compress, callback) {
|
||||
let outputFile = fs.createWriteStream(path);
|
||||
b.bundle().on('error', console.error).pipe(outputFile);
|
||||
outputFile.on('finish', () => {
|
||||
if (compress) {
|
||||
fs.writeFileSync(path, minifyJs(path));
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function bundleVendorJs(compress) {
|
||||
let b = browserify();
|
||||
for (let lib of external_js) {
|
||||
b.require(lib);
|
||||
}
|
||||
if (!process.argv.includes('--no-transpile')) {
|
||||
b.add(require.resolve('babel-polyfill'));
|
||||
}
|
||||
const file = './public/js/vendor.min.js';
|
||||
writeJsBundle(b, file, compress, () => {
|
||||
if (process.argv.includes('--gzip')) {
|
||||
gzipFile(file);
|
||||
}
|
||||
console.info('Bundled vendor JS');
|
||||
});
|
||||
}
|
||||
|
||||
function bundleAppJs(b, compress, callback) {
|
||||
const file = './public/js/app.min.js';
|
||||
writeJsBundle(b, file, compress, () => {
|
||||
if (process.argv.includes('--gzip')) {
|
||||
gzipFile(file);
|
||||
}
|
||||
console.info('Bundled app JS');
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function bundleJs() {
|
||||
const browserify = require('browserify');
|
||||
|
||||
function minifyJs(path) {
|
||||
return require('terser').minify(
|
||||
fs.readFileSync(path, 'utf-8'), {compress: {unused: false}}).code;
|
||||
}
|
||||
|
||||
function writeJsBundle(b, path, compress, callback) {
|
||||
let outputFile = fs.createWriteStream(path);
|
||||
b.bundle().pipe(outputFile);
|
||||
outputFile.on('finish', () => {
|
||||
if (compress) {
|
||||
fs.writeFileSync(path, minifyJs(path));
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
if (!process.argv.includes('--no-vendor-js')) {
|
||||
let b = browserify();
|
||||
for (let lib of external_js) {
|
||||
b.require(lib);
|
||||
}
|
||||
if (!process.argv.includes('--no-transpile')) {
|
||||
b.add(require.resolve('babel-polyfill'));
|
||||
}
|
||||
const file = './public/js/vendor.min.js';
|
||||
writeJsBundle(b, file, true, () => {
|
||||
if (process.argv.includes('--gzip')) {
|
||||
gzipFile(file);
|
||||
}
|
||||
console.info('Bundled vendor JS');
|
||||
});
|
||||
bundleVendorJs(true);
|
||||
}
|
||||
|
||||
if (!process.argv.includes('--no-app-js')) {
|
||||
let b = browserify({debug: process.argv.includes('--debug')});
|
||||
let watchify = require('watchify');
|
||||
let b = browserify({ debug: process.argv.includes('--debug') });
|
||||
if (!process.argv.includes('--no-transpile')) {
|
||||
b = b.transform('babelify');
|
||||
}
|
||||
b = b.external(external_js).add(glob.sync('./js/**/*.js'));
|
||||
const compress = !process.argv.includes('--debug');
|
||||
const file = './public/js/app.min.js';
|
||||
writeJsBundle(b, file, compress, () => {
|
||||
if (process.argv.includes('--gzip')) {
|
||||
gzipFile(file);
|
||||
}
|
||||
console.info('Bundled app JS');
|
||||
});
|
||||
bundleAppJs(b, compress, () => { });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,8 +226,8 @@ function bundleConfig() {
|
|||
}
|
||||
const config = {
|
||||
meta: {
|
||||
version: getVersion(),
|
||||
buildDate: new Date().toUTCString()
|
||||
version: getVersion(),
|
||||
buildDate: new Date().toUTCString()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -255,31 +265,31 @@ function bundleWebAppFiles() {
|
|||
|
||||
Promise.all(webapp_icons.map(icon => {
|
||||
return Jimp.read('./img/app.png')
|
||||
.then(file => {
|
||||
file.resize(icon.size, Jimp.AUTO, Jimp.RESIZE_BEZIER)
|
||||
.write(path.join('./public/img/', icon.name));
|
||||
});
|
||||
.then(file => {
|
||||
file.resize(icon.size, Jimp.AUTO, Jimp.RESIZE_BEZIER)
|
||||
.write(path.join('./public/img/', icon.name));
|
||||
});
|
||||
}))
|
||||
.then(() => {
|
||||
console.info('Generated webapp icons');
|
||||
});
|
||||
.then(() => {
|
||||
console.info('Generated webapp icons');
|
||||
});
|
||||
|
||||
Promise.all(webapp_splash_screens.map(dim => {
|
||||
return Jimp.read('./img/splash.png')
|
||||
.then(file => {
|
||||
file.resize(dim.center, Jimp.AUTO, Jimp.RESIZE_BEZIER)
|
||||
.background(0xFFFFFFFF)
|
||||
.contain(dim.w, dim.center,
|
||||
Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||
.contain(dim.w, dim.h,
|
||||
Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||
.write(path.join('./public/img/',
|
||||
'apple-touch-startup-image-' + dim.w + 'x' + dim.h + '.png'));
|
||||
});
|
||||
.then(file => {
|
||||
file.resize(dim.center, Jimp.AUTO, Jimp.RESIZE_BEZIER)
|
||||
.background(0xFFFFFFFF)
|
||||
.contain(dim.w, dim.center,
|
||||
Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||
.contain(dim.w, dim.h,
|
||||
Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||
.write(path.join('./public/img/',
|
||||
'apple-touch-startup-image-' + dim.w + 'x' + dim.h + '.png'));
|
||||
});
|
||||
}))
|
||||
.then(() => {
|
||||
console.info('Generated splash screens');
|
||||
});
|
||||
.then(() => {
|
||||
console.info('Generated splash screens');
|
||||
});
|
||||
}
|
||||
|
||||
function makeOutputDirs() {
|
||||
|
@ -298,22 +308,66 @@ function makeOutputDirs() {
|
|||
}
|
||||
}
|
||||
|
||||
function watch() {
|
||||
chokidar.watch('./fonts/**/*').on('change', bundleBinaryAssets);
|
||||
chokidar.watch('./img/**/*').on('change', bundleWebAppFiles);
|
||||
chokidar.watch('./html/**/*.tpl').on('change', bundleHtml);
|
||||
chokidar.watch('./css/**/*.styl').on('change', bundleCss);
|
||||
|
||||
bundleBinaryAssets();
|
||||
bundleWebAppFiles();
|
||||
bundleCss();
|
||||
bundleHtml();
|
||||
|
||||
let watchify = require('watchify');
|
||||
let b = browserify({
|
||||
debug: process.argv.includes('--debug'),
|
||||
entries: ['js/main.js'],
|
||||
cache: {},
|
||||
packageCache: {},
|
||||
});
|
||||
|
||||
b.plugin(watchify);
|
||||
|
||||
if (!process.argv.includes('--no-transpile')) {
|
||||
b = b.transform('babelify');
|
||||
}
|
||||
b = b.external(external_js).add(glob.sync('./js/**/*.js'));
|
||||
const compress = false;
|
||||
|
||||
function bundle(id) {
|
||||
console.info("Rebundling app JS...");
|
||||
let start = new Date();
|
||||
bundleAppJs(b, compress, () => {
|
||||
let end = new Date() - start;
|
||||
console.info('Rebundled in %ds.', end / 1000)
|
||||
});
|
||||
}
|
||||
|
||||
b.on('update', bundle);
|
||||
bundle();
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
makeOutputDirs();
|
||||
bundleConfig();
|
||||
if (!process.argv.includes('--no-binary-assets')) {
|
||||
bundleBinaryAssets();
|
||||
}
|
||||
if (!process.argv.includes('--no-web-app-files')) {
|
||||
bundleWebAppFiles();
|
||||
}
|
||||
if (!process.argv.includes('--no-html')) {
|
||||
bundleHtml();
|
||||
}
|
||||
if (!process.argv.includes('--no-css')) {
|
||||
bundleCss();
|
||||
}
|
||||
if (!process.argv.includes('--no-js')) {
|
||||
bundleJs();
|
||||
if (process.argv.includes('--watch')) {
|
||||
watch();
|
||||
} else {
|
||||
if (!process.argv.includes('--no-binary-assets')) {
|
||||
bundleBinaryAssets();
|
||||
}
|
||||
if (!process.argv.includes('--no-web-app-files')) {
|
||||
bundleWebAppFiles();
|
||||
}
|
||||
if (!process.argv.includes('--no-html')) {
|
||||
bundleHtml();
|
||||
}
|
||||
if (!process.argv.includes('--no-css')) {
|
||||
bundleCss();
|
||||
}
|
||||
if (!process.argv.includes('--no-js')) {
|
||||
bundleJs();
|
||||
}
|
||||
}
|
||||
|
|
5143
client/package-lock.json
generated
5143
client/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,8 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node build.js",
|
||||
"watch": "c1=\"\";while :;do c2=$(find html js css img -type f -and -not -iname '*autogen*'|sort|xargs cat|md5sum);[[ $c1 != $c2 ]]&&npm run build -- --debug --no-vendor-js;c1=$c2;sleep 1;done"
|
||||
"watch": "bash watch.sh",
|
||||
"watchify": "watchify ./js/**/*.js -o ./public/js/app.min.js -d -v"
|
||||
},
|
||||
"dependencies": {
|
||||
"dompurify": "^2.0.17",
|
||||
|
@ -21,12 +22,14 @@
|
|||
"babel-preset-env": "^1.7.0",
|
||||
"babelify": "^8.0.0",
|
||||
"browserify": "^16.2.2",
|
||||
"chokidar": "^3.5.1",
|
||||
"csso": "^3.5.1",
|
||||
"glob": "^7.1.2",
|
||||
"html-minifier": "^3.5.18",
|
||||
"jimp": "^0.13.0",
|
||||
"stylus": "^0.54.5",
|
||||
"terser": "^3.7.7",
|
||||
"underscore": "^1.9.1"
|
||||
"underscore": "^1.9.1",
|
||||
"watchify": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
15
client/watch.sh
Normal file
15
client/watch.sh
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
npm run watchify &
|
||||
|
||||
c1="";
|
||||
while :; do
|
||||
c2=$(find html css img -type f -and -not -iname '*autogen*'|sort|xargs cat|md5sum);
|
||||
[[ $c1 != $c2 ]] && npm run build -- --debug --no-js --no-binary-assets --no-web-app-files
|
||||
c1=$c2;
|
||||
sleep 1;
|
||||
done
|
||||
|
||||
wait
|
Reference in a new issue