embark-area-51/lib/modules/pipeline/webpackProcess.js
Pascal Precht a0ef234fea
feat(modules/pipeline): move pipeline into its own module plugin
This is the first step of refactoring Embark's pipeline abstraction into
dedicated plugin modules that take advantage of Embark's event system.

With this commit we're moving `Pipeline` into `lib/modules/pipeline` and
introduce a new command handler `pipeline:build`. Embark's engine now
requests builds via this command handler.

Notice that `Watch` still lives in `lib/pipeline` as this is a step-by-step
refactoring to reduce chances of introducing regressions.
2018-10-22 19:35:58 +02:00

140 lines
4.4 KiB
JavaScript

const constants = require('../../constants');
const fs = require('../../core/fs');
const ProcessWrapper = require('../../core/processes/processWrapper');
const webpack = require('webpack');
const writeFile = require('util').promisify(require('fs').writeFile);
const {errorMessage, recursiveMerge} = require('../utils/utils');
// TODO: refactor into lib/core/config once pipeline is a proper embark module
const defaultPipelineConfig = {
typescript: false
};
const pipelineConfigPath = fs.dappPath(
require(fs.dappPath('embark.json')).config || 'config/',
'pipeline.js'
);
let webpackProcess;
class WebpackProcess extends ProcessWrapper {
constructor(options) {
super(options);
this.webpackConfigName = options.webpackConfigName;
}
async build(assets, importsList, callback) {
try {
await this.webpackRun(assets, importsList, callback);
} catch (e) {
callback(errorMessage(e));
}
}
async webpackRun(assets, importsList, callback) {
try {
await writeFile(
fs.dappPath('.embark/embark-aliases.json'),
JSON.stringify(importsList)
);
await writeFile(
fs.dappPath('.embark/embark-assets.json'),
JSON.stringify(assets)
);
let pipelineConfig = defaultPipelineConfig;
if (fs.existsSync(pipelineConfigPath)) {
delete require.cache[pipelineConfigPath];
pipelineConfig = recursiveMerge(
recursiveMerge(true, pipelineConfig),
require(pipelineConfigPath)
);
}
await writeFile(
fs.dappPath('.embark/embark-pipeline.json'),
JSON.stringify(pipelineConfig)
);
} catch (e) {
return callback(errorMessage(e));
}
const dappConfigPath = fs.dappPath('webpack.config.js');
const defaultConfigPath = fs.embarkPath('lib/modules/pipeline', 'webpack.config.js');
let config, configPath;
try {
if (fs.existsSync(dappConfigPath)) {
configPath = dappConfigPath;
delete require.cache[configPath];
} else {
configPath = defaultConfigPath;
}
config = require(configPath);
// valid config types: https://webpack.js.org/configuration/configuration-types/
// + function that returns a config object
// + function that returns a promise for a config object
// + array of named config objects
// + config object
if (typeof config === 'function') {
config = await config(this.webpackConfigName);
} else if (Array.isArray(config)) {
config = config.filter(cfg => cfg.name === this.webpackConfigName);
if (!config.length) {
return callback(`no webpack config has the name '${this.webpackConfigName}'`);
}
if (config.length > 1) {
console.warn(`detected ${config.length} webpack configs having the name '${this.webpackConfigName}', using the first one`);
}
config = config[0];
}
} catch (e) {
console.error(`error while loading webpack config ${configPath}`);
callback(errorMessage(e));
}
if (typeof config !== 'object' || config === null) {
return callback('bad webpack config, the resolved config was null or not an object');
}
webpack(config).run(async (err, stats) => {
if (err) {
return callback(errorMessage(err));
}
if (!config.stats || config.stats === 'none') {
return callback();
}
try {
this._log('info', 'writing file '+ ('.embark/stats.report').bold.dim);
await writeFile(
fs.dappPath('.embark/stats.report'),
stats.toString(config.stats)
);
this._log('info', 'writing file ' + ('.embark/stats.json').bold.dim);
await writeFile(
fs.dappPath('.embark/stats.json'),
JSON.stringify(stats.toJson(config.stats))
);
if (stats.hasErrors()) {
const errors = stats.toJson(config.stats).errors.join('\n');
return callback(errors);
}
callback();
} catch (e) {
return callback(errorMessage(e));
}
});
}
}
process.on('message', (msg) => {
if (msg.action === constants.pipeline.init) {
webpackProcess = new WebpackProcess(msg.options);
return process.send({result: constants.pipeline.initiated});
}
if (msg.action === constants.pipeline.build) {
return webpackProcess.build(msg.assets, msg.importsList, (err) => {
process.send({result: constants.pipeline.built, error: err});
});
}
});