use embark's webpack config, or a dapp's webpack config if it exists

This commit is contained in:
Michael Bradley, Jr 2018-08-16 15:53:23 -05:00
parent c60d26e258
commit 2f2f007d5c

View File

@ -1,12 +1,8 @@
const async = require('async');
const webpack = require('webpack');
const utils = require('../utils/utils');
const fs = require('../core/fs');
const constants = require('../constants'); const constants = require('../constants');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); const fs = require('../core/fs');
const ProcessWrapper = require('../core/processes/processWrapper'); const ProcessWrapper = require('../core/processes/processWrapper');
const path = require('path'); const webpack = require('webpack');
const glob = require('glob'); const writeFile = require('util').promisify(require('fs').writeFile);
let webpackProcess; let webpackProcess;
@ -14,195 +10,120 @@ class WebpackProcess extends ProcessWrapper {
constructor(options) { constructor(options) {
super(options); super(options);
this.webpackConfigName = options.webpackConfigName; this.webpackConfigName = options.webpackConfigName;
if (!process.env.DAPP_PATH) {
process.env.DAPP_PATH = fs.dappPath();
}
if (!process.env.EMBARK_PATH) {
process.env.EMBARK_PATH = fs.embarkPath();
}
} }
build(file, importsList, callback) { async build(assets, importsList, callback) {
try {
await this.webpackRun(assets, importsList, callback);
} catch (e) {
console.error(e.message);
callback(e);
// ?? should return e or e.message
}
}
async webpackRun(assets, importsList, callback) {
const self = this; const self = this;
let realCwd; try {
await writeFile(
async.waterfall([ fs.dappPath('.embark/embark-aliases.json'),
function changeCwd(next) { JSON.stringify(importsList)
realCwd = utils.pwd(); );
process.chdir(fs.embarkPath('')); await writeFile(
next(); fs.dappPath('.embark/embark-assets.json'),
}, JSON.stringify(assets)
);
function runWebpack(next) { } catch (e) {
self.webpackRun(file.filename, {}, true, importsList, true, realCwd, next); console.error(e.message);
}, return callback(e);
// ?? should return e or e.message
function changeCwdBack(next) {
process.chdir(realCwd);
next();
}
], (err) => {
process.chdir(realCwd);
callback(err);
});
} }
webpackRun(filename, options, includeModules, importsList, detectErrors, realCwd, callback) { const dappConfigPath = fs.dappPath('webpack.config.js');
const self = this; const defaultConfigPath = fs.embarkPath('webpack.config.js');
glob(fs.dappPath('.embark/versions/*/*'), (err, files) => {
let versions; let config, configPath;
if (err) { try {
console.error(err); if (fs.existsSync(dappConfigPath)) {
versions = []; delete require.cache[dappConfigPath];
configPath = dappConfigPath;
config = require(dappConfigPath);
} else { } else {
versions = files; configPath = defaultConfigPath;
config = require(defaultConfigPath);
} }
let defaultOptions = { // valid config types: https://webpack.js.org/configuration/configuration-types/
mode: self.env === 'production' ? 'production' : 'none', // + function that returns a config object
// devtool: self.env === 'development' ? 'source-map' : false, // + function that returns a promise for a config object
// pipeline would need to copy .map files to dist/ target dir // + array of named config objects
// note: generating full source maps ('source-map') roughly doubles build time // + config object
entry: fs.dappPath(filename), if (typeof config === 'function') {
output: { config = await config(self.webpackConfigName);
globalObject: 'typeof self !== \'undefined\' ? self : this', } else if (Array.isArray(config)) {
libraryExport: 'default', config = config.filter(cfg => cfg.name === self.webpackConfigName);
libraryTarget: 'umd', if (!config.length) {
path: fs.dappPath('.embark'), const errMsg = `no webpack config has the name '${self.webpackConfigName}'`;
filename: filename, console.error(errMsg);
umdNamedDefine: true return callback(errMsg);
}, // ?? should the message be wrapped in new Error()
// profile: true,
// stats: 'verbose',
// note: generating and writing to disk verbose stats increases build time
resolve: {
alias: importsList,
modules: [
fs.dappPath('node_modules'),
...versions,
fs.embarkPath('node_modules')
]
},
plugins: [
new HardSourceWebpackPlugin({
cacheDirectory: fs.dappPath('node_modules/.cache/hard-source'),
// ufglify (wp mode: production) will still save its cache in embark's node_modules/.cache/
environmentHash: {
root: fs.dappPath()
} }
}), if (config.length > 1) {
new HardSourceWebpackPlugin.ExcludeModulePlugin( console.warn(
[{test: /app[\\/]|contracts[\\/]/}] `detected ${config.length} webpack configs having the name '${self.webpackConfigName}', using the first one`
)
]
};
let webpackOptions = utils.recursiveMerge(defaultOptions, options);
if (includeModules) {
webpackOptions.module = {
rules: [
{
test: /\.css$/,
use: [{loader: "style-loader"}, {loader: "css-loader"}]
},
{
test: /\.scss$/,
use: [{loader: "style-loader"}, {loader: "css-loader"}]
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /(node_modules|bower_components|\.embark[\\/]versions)/,
options: {
presets: [
[
"@babel/preset-env", {
modules: false,
targets: {
browsers: ["last 1 version", "not dead", "> 0.2%"]
}
}
],
"@babel/preset-react"
].map(pkg => {
if (Array.isArray(pkg)) {
let _pkg = pkg[0];
pkg[0] = require.resolve(_pkg);
return pkg;
} else {
return require.resolve(pkg);
}
}),
plugins: [
"babel-plugin-webpack-aliases",
[
"@babel/plugin-transform-runtime", {
corejs: 2,
useESModules: true
}
]
].map(pkg => {
if (Array.isArray(pkg)) {
let _pkg = pkg[0];
pkg[0] = require.resolve(_pkg);
return pkg;
} else {
return require.resolve(pkg);
}
}),
compact: false
}
}
]
};
let dappBabelrc = path.join(realCwd, '.babelrc');
if (fs.existsSync(dappBabelrc)) {
webpackOptions.module.rules[3].options.extends = dappBabelrc;
}
}
webpack(webpackOptions).run((err, stats) => {
async.waterfall([
function checkStatsError(next) {
if (err) {
console.error(err);
return next(err);
}
if (!detectErrors) {
return next();
}
if (stats.hasErrors()) {
return next(
stats.toJson(webpackOptions.stats).errors.join("\n")
); );
} }
next(); config = config[0];
}//, } else {
// function writeStatsReport(next) { // proceed with the value obtained from require(dapp/default/Config)
// if (detectErrors) { }
// self._log('info', 'writing file '+ ('.embark/stats.report').bold.dim); } catch (e) {
// } console.error(`error while loading webpack config ${configPath}`);
// fs.writeFile( console.error(e.message);
// path.join(fs.dappPath('.embark'), 'stats.report'), callback(e);
// stats.toString(webpackOptions.stats), // ?? should return e or e.message
// next }
// );
// }, if (typeof config !== 'object' || config === null) {
// function writeStatsJSON(next) { const errMsg = 'bad webpack config, the resolved config was null or not an object';
// if (detectErrors) { console.error(errMsg);
// self._log('info','writing file '+ ('.embark/stats.json').bold.dim); return callback(errMsg);
// } // ?? should the message be wrapped in new Error()
// fs.writeFile( }
// path.join(fs.dappPath('.embark'), 'stats.json'),
// JSON.stringify(stats.toJson(webpackOptions.stats)), webpack(config).run(async (err, stats) => {
// next if (err) {
// ); console.error(err);
// } return callback(err);
// note: to visualize the stats info in a browser, do... }
// `npx webpack-bundle-analyzer <dapp_dir>/.embark/stats.json` try {
], (err) => { if (config.stats && config.stats !== 'none') {
callback(err); self._log('info', 'writing file '+ ('.embark/stats.report').bold.dim);
}); await writeFile(
}); fs.dappPath('.embark/stats.report'),
stats.toString(config.stats)
);
self._log('info','writing file '+ ('.embark/stats.json').bold.dim);
await writeFile(
fs.dappPath('.embark/stats.json'),
JSON.stringify(stats.toJson(config.stats))
);
}
} catch (e) {
console.error(e.message);
return callback(err);
}
if (config.stats && stats.hasErrors()) {
const errors = stats.toJson(config.stats).errors.join('\n');
console.error(errors);
return callback(errors);
}
callback();
}); });
} }
} }
@ -214,7 +135,7 @@ process.on('message', (msg) => {
} }
if (msg.action === constants.pipeline.build) { if (msg.action === constants.pipeline.build) {
return webpackProcess.build(msg.file, msg.importsList, (err) => { return webpackProcess.build(msg.assets, msg.importsList, (err) => {
process.send({result: constants.pipeline.built, error: err}); process.send({result: constants.pipeline.built, error: err});
}); });
} }