pixelplanet/scripts/build.js

205 lines
5.4 KiB
JavaScript

/*
* We got so many locals that building them all in one go can lead to out-of-memory error
* Lets split that here
*/
const path = require('path');
const fs = require('fs');
const { spawn } = require('child_process');
const webpack = require('webpack');
const minifyCss = require('./minifyCss');
const serverConfig = require('../webpack.config.server.js');
const clientConfig = require('../webpack.config.client.js');
const { getAllAvailableLocals } = clientConfig;
let langs = 'all';
let doBuildServer = false;
let doBuildClient = false;
let parallel = false;
let recursion = false;
for (let i = 0; i < process.argv.length; i += 1) {
switch (process.argv[i]) {
case '--langs': {
const newLangs = process.argv[++i];
if (newLangs) langs = newLangs;
break;
}
case '--client':
doBuildClient = true;
break;
case `--server`:
doBuildServer = true;
break;
case '--parallel':
parallel = true;
break;
case '--recursion':
recursion = true;
break;
default:
// nothing
}
}
if (!doBuildServer && !doBuildClient) {
doBuildServer = true;
doBuildClient = true;
}
function compile(webpackConfig) {
return new Promise((resolve, reject) => {
webpack(webpackConfig, (err, stats) => {
if (err) {
return reject(err);
}
const statsConfig = (webpackConfig.length) ? webpackConfig[0].stats : webpackConfig.stats;
console.log(stats.toString(statsConfig))
return resolve();
});
});
}
function buildServer() {
console.log('-----------------------------');
console.log(`Build server...`);
console.log('-----------------------------');
const ts = Date.now();
return new Promise((resolve, reject) => {
const argsc = (langs === 'all')
? ['webpack', '--env', 'extract', '--config', './webpack.config.server.js']
: ['webpack', '--config', './webpack.config.server.js']
const serverCompile = spawn('npx', argsc);
serverCompile.stdout.on('data', (data) => {
console.log(data.toString());
});
serverCompile.stderr.on('data', (data) => {
console.error(data.toString());
});
serverCompile.on('close', (code) => {
if (code) {
reject(new Error('Server compilation failed!'));
} else {
console.log('---------------------------------------');
console.log(`Server Compilation finished in ${Math.floor((Date.now() - ts) / 1000)}s`);
console.log('---------------------------------------');
resolve();
}
});
});
}
function buildClients(slangs) {
return new Promise((resolve, reject) => {
const clientCompile = spawn('npm', ['run', 'build', '--', '--client', '--recursion', '--langs', slangs.join(',')]);
clientCompile.stdout.on('data', (data) => {
console.log(data.toString());
});
clientCompile.stderr.on('data', (data) => {
console.error(data.toString());
});
clientCompile.on('close', (code) => {
if (code) {
reject(new Error('Client compilation failed!'));
} else {
resolve();
}
});
});
}
async function buildClientsSync(avlangs) {
for(let i = 0; i < avlangs.length; i += 1) {
const lang = avlangs[i];
console.log(`Build client for locale ${lang}...`);
await compile(clientConfig({
development: false,
analyze: false,
extract: false,
locale: lang,
clean: false,
readonly: recursion,
}));
}
}
function buildClientsParallel(avlangs) {
const st = Date.now();
const numProc = 3;
let nump = Math.floor(avlangs.length / numProc);
if (!nump) nump = 1;
const promises = [];
while (avlangs.length >= nump) {
const slangs = avlangs.splice(0, nump);
promises.push(buildClients(slangs));
}
if (avlangs.length) {
promises.push(buildClientsSync(avlangs));
}
return Promise.all(promises);
}
async function buildProduction() {
const st = Date.now();
// cleanup old files
if (!recursion) {
fs.rmSync(path.resolve(__dirname, '..', 'node_modules', '.cache', 'webpack'), { recursive: true, force: true });
}
// decide which languages to build
let avlangs = getAllAvailableLocals();
if (langs !== 'all') {
avlangs = langs.split(',').map((l) => l.trim())
.filter((l) => avlangs.includes(l));
if (!avlangs.length) {
console.error(`ERROR: language ${langs} not available`);
process.exit(1);
return;
}
}
console.log('Building locales:', avlangs);
const promises = [];
if (doBuildServer) {
promises.push(buildServer());
}
if (doBuildClient) {
if (!recursion) {
console.log(
'Building one package seperately to populate cache and possibly extract langs...',
);
await compile(clientConfig({
development: false,
analyze: false,
extract: (langs === 'all'),
locale: avlangs.shift(),
clean: true,
readonly: false,
}));
console.log('-----------------------------');
console.log(`Minify CSS assets...`);
console.log('-----------------------------');
await minifyCss();
}
if (parallel) {
promises.push(buildClientsParallel(avlangs));
} else {
promises.push(buildClientsSync(avlangs));
}
}
await Promise.all(promises);
if (!recursion) {
console.log(`Finished building in ${(Date.now() - st) / 1000}s`);
} else {
console.log(`Worker done in ${(Date.now() - st) / 1000}s`);
}
}
buildProduction();