2016-11-18 12:01:33 +03:00
|
|
|
'use strict';
|
|
|
|
|
|
2020-01-14 15:11:47 -05:00
|
|
|
const os = require('os');
|
2019-09-13 18:24:21 -04:00
|
|
|
const winston = require('winston');
|
|
|
|
|
const nconf = require('nconf');
|
|
|
|
|
const _ = require('lodash');
|
2020-11-06 13:44:29 -05:00
|
|
|
const path = require('path');
|
|
|
|
|
const mkdirp = require('mkdirp');
|
2016-11-18 12:01:33 +03:00
|
|
|
|
2019-09-13 18:24:21 -04:00
|
|
|
const cacheBuster = require('./cacheBuster');
|
2021-01-06 18:36:50 -07:00
|
|
|
const { aliases } = require('./aliases');
|
2021-02-03 23:53:16 -07:00
|
|
|
|
2019-09-13 18:24:21 -04:00
|
|
|
let meta;
|
2016-11-19 14:24:37 -05:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
const targetHandlers = {
|
|
|
|
|
'plugin static dirs': async function () {
|
|
|
|
|
await meta.js.linkStatics();
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
2020-10-14 22:49:39 -04:00
|
|
|
'requirejs modules': async function (parallel) {
|
|
|
|
|
await meta.js.buildModules(parallel);
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
2020-10-14 22:49:39 -04:00
|
|
|
'client js bundle': async function (parallel) {
|
|
|
|
|
await meta.js.buildBundle('client', parallel);
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
2020-10-14 22:49:39 -04:00
|
|
|
'admin js bundle': async function (parallel) {
|
|
|
|
|
await meta.js.buildBundle('admin', parallel);
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
|
|
|
|
javascript: [
|
|
|
|
|
'plugin static dirs',
|
|
|
|
|
'requirejs modules',
|
|
|
|
|
'client js bundle',
|
|
|
|
|
'admin js bundle',
|
|
|
|
|
],
|
2020-10-14 22:49:39 -04:00
|
|
|
'client side styles': async function (parallel) {
|
|
|
|
|
await meta.css.buildBundle('client', parallel);
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
2020-10-14 22:49:39 -04:00
|
|
|
'admin control panel styles': async function (parallel) {
|
|
|
|
|
await meta.css.buildBundle('admin', parallel);
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
|
|
|
|
styles: [
|
|
|
|
|
'client side styles',
|
|
|
|
|
'admin control panel styles',
|
|
|
|
|
],
|
2020-10-14 22:49:39 -04:00
|
|
|
templates: async function () {
|
|
|
|
|
await meta.templates.compile();
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
2020-10-14 22:49:39 -04:00
|
|
|
languages: async function () {
|
|
|
|
|
await meta.languages.build();
|
2017-05-17 16:33:31 -06:00
|
|
|
},
|
|
|
|
|
};
|
2016-12-13 15:43:20 +03:00
|
|
|
|
2021-02-04 00:01:39 -07:00
|
|
|
const aliasMap = Object.keys(aliases).reduce((prev, key) => {
|
2017-05-17 16:33:31 -06:00
|
|
|
var arr = aliases[key];
|
2021-02-04 00:01:39 -07:00
|
|
|
arr.forEach((alias) => {
|
2017-05-17 16:33:31 -06:00
|
|
|
prev[alias] = key;
|
|
|
|
|
});
|
|
|
|
|
prev[key] = key;
|
|
|
|
|
return prev;
|
|
|
|
|
}, {});
|
2016-11-18 12:01:33 +03:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
async function beforeBuild(targets) {
|
|
|
|
|
const db = require('../database');
|
2018-05-16 15:53:49 -04:00
|
|
|
require('colors');
|
2017-12-19 12:06:56 -05:00
|
|
|
process.stdout.write(' started'.green + '\n'.reset);
|
2020-10-14 22:49:39 -04:00
|
|
|
try {
|
|
|
|
|
await db.init();
|
|
|
|
|
meta = require('./index');
|
|
|
|
|
await meta.themes.setupPaths();
|
|
|
|
|
const plugins = require('../plugins');
|
|
|
|
|
await plugins.prepareForBuild(targets);
|
2020-11-06 13:44:29 -05:00
|
|
|
await mkdirp(path.join(__dirname, '../../build/public'));
|
2020-10-14 22:49:39 -04:00
|
|
|
} catch (err) {
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.error(`[build] Encountered error preparing for build\n${err.stack}`);
|
2020-10-14 22:49:39 -04:00
|
|
|
throw err;
|
|
|
|
|
}
|
2017-05-17 16:33:31 -06:00
|
|
|
}
|
2016-11-18 12:01:33 +03:00
|
|
|
|
2021-02-04 00:01:39 -07:00
|
|
|
const allTargets = Object.keys(targetHandlers).filter(name => typeof targetHandlers[name] === 'function');
|
2017-02-08 10:42:55 -05:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
async function buildTargets(targets, parallel) {
|
|
|
|
|
const length = Math.max.apply(Math, targets.map(name => name.length));
|
|
|
|
|
|
|
|
|
|
if (parallel) {
|
|
|
|
|
await Promise.all(
|
|
|
|
|
targets.map(
|
2021-02-03 23:59:08 -07:00
|
|
|
target => step(target, parallel, `${_.padStart(target, length)} `)
|
2020-10-14 22:49:39 -04:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
for (const target of targets) {
|
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
2021-02-03 23:59:08 -07:00
|
|
|
await step(target, parallel, `${_.padStart(target, length)} `);
|
2020-10-14 22:49:39 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-01 13:51:14 +03:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
async function step(target, parallel, targetStr) {
|
|
|
|
|
const startTime = Date.now();
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.info(`[build] ${targetStr} build started`);
|
2020-10-14 22:49:39 -04:00
|
|
|
try {
|
|
|
|
|
await targetHandlers[target](parallel);
|
|
|
|
|
const time = (Date.now() - startTime) / 1000;
|
|
|
|
|
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.info(`[build] ${targetStr} build completed in ${time}sec`);
|
2020-10-14 22:49:39 -04:00
|
|
|
} catch (err) {
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.error(`[build] ${targetStr} build failed`);
|
2020-10-14 22:49:39 -04:00
|
|
|
throw err;
|
|
|
|
|
}
|
2017-05-17 16:33:31 -06:00
|
|
|
}
|
2016-12-01 13:51:14 +03:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
exports.build = async function (targets, options) {
|
|
|
|
|
if (!options) {
|
2018-07-01 22:11:38 -06:00
|
|
|
options = {};
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-17 16:33:31 -06:00
|
|
|
if (targets === true) {
|
|
|
|
|
targets = allTargets;
|
|
|
|
|
} else if (!Array.isArray(targets)) {
|
|
|
|
|
targets = targets.split(',');
|
2017-02-08 10:42:55 -05:00
|
|
|
}
|
|
|
|
|
|
2020-01-14 15:11:47 -05:00
|
|
|
let series = nconf.get('series') || options.series;
|
|
|
|
|
if (series === undefined) {
|
|
|
|
|
// Detect # of CPUs and select strategy as appropriate
|
|
|
|
|
winston.verbose('[build] Querying CPU core count for build strategy');
|
|
|
|
|
const cpus = os.cpus();
|
|
|
|
|
series = cpus.length < 4;
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.verbose(`[build] System returned ${cpus.length} cores, opting for ${series ? 'series' : 'parallel'} build strategy`);
|
2020-01-14 15:11:47 -05:00
|
|
|
}
|
2018-07-01 22:11:38 -06:00
|
|
|
|
2017-05-17 16:33:31 -06:00
|
|
|
targets = targets
|
|
|
|
|
// get full target name
|
2021-02-04 00:01:39 -07:00
|
|
|
.map((target) => {
|
2017-05-17 16:33:31 -06:00
|
|
|
target = target.toLowerCase().replace(/-/g, '');
|
2021-01-06 18:36:50 -07:00
|
|
|
if (!aliasMap[target]) {
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.warn(`[build] Unknown target: ${target}`);
|
2018-10-20 14:40:48 -04:00
|
|
|
if (target.includes(',')) {
|
2018-01-19 13:27:09 -05:00
|
|
|
winston.warn('[build] Are you specifying multiple targets? Separate them with spaces:');
|
|
|
|
|
winston.warn('[build] e.g. `./nodebb build adminjs tpl`');
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-17 16:33:31 -06:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-06 18:36:50 -07:00
|
|
|
return aliasMap[target];
|
2017-05-17 16:33:31 -06:00
|
|
|
})
|
|
|
|
|
// filter nonexistent targets
|
2019-01-12 12:28:53 -07:00
|
|
|
.filter(Boolean);
|
|
|
|
|
|
|
|
|
|
// map multitargets to their sets
|
|
|
|
|
targets = _.uniq(_.flatMap(targets, target => (
|
|
|
|
|
Array.isArray(targetHandlers[target]) ?
|
|
|
|
|
targetHandlers[target] :
|
|
|
|
|
target
|
|
|
|
|
)));
|
2017-05-17 16:33:31 -06:00
|
|
|
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.verbose(`[build] building the following targets: ${targets.join(', ')}`);
|
2017-05-18 01:32:20 -06:00
|
|
|
|
2017-05-17 16:33:31 -06:00
|
|
|
if (!targets) {
|
|
|
|
|
winston.info('[build] No valid targets supplied. Aborting.');
|
2020-10-14 22:49:39 -04:00
|
|
|
return;
|
2017-05-17 16:33:31 -06:00
|
|
|
}
|
|
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
try {
|
|
|
|
|
await beforeBuild(targets);
|
|
|
|
|
const threads = parseInt(nconf.get('threads'), 10);
|
|
|
|
|
if (threads) {
|
|
|
|
|
require('./minifier').maxThreads = threads - 1;
|
|
|
|
|
}
|
2017-05-17 16:33:31 -06:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
if (!series) {
|
|
|
|
|
winston.info('[build] Building in parallel mode');
|
|
|
|
|
} else {
|
|
|
|
|
winston.info('[build] Building in series mode');
|
2016-11-18 12:01:33 +03:00
|
|
|
}
|
|
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
const startTime = Date.now();
|
|
|
|
|
await buildTargets(targets, !series);
|
|
|
|
|
const totalTime = (Date.now() - startTime) / 1000;
|
|
|
|
|
await cacheBuster.write();
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.info(`[build] Asset compilation successful. Completed in ${totalTime}sec.`);
|
2020-10-14 22:49:39 -04:00
|
|
|
} catch (err) {
|
2021-02-03 23:59:08 -07:00
|
|
|
winston.error(`[build] Encountered error during build step\n${err.stack ? err.stack : err}`);
|
2020-10-14 22:49:39 -04:00
|
|
|
throw err;
|
|
|
|
|
}
|
2019-09-13 18:24:21 -04:00
|
|
|
};
|
2017-01-23 21:06:34 -07:00
|
|
|
|
2020-10-14 22:49:39 -04:00
|
|
|
exports.buildAll = async function () {
|
|
|
|
|
await exports.build(allTargets);
|
2017-02-18 02:30:48 -07:00
|
|
|
};
|
2019-09-13 18:24:21 -04:00
|
|
|
|
|
|
|
|
require('../promisify')(exports);
|