Merge pull request #720 from embark-framework/features/extensible-pipeline

extensible pipeline
This commit is contained in:
Iuri Matias 2018-08-25 16:54:40 -04:00 committed by GitHub
commit 782e7b04e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 473 additions and 353 deletions

View File

@ -1,8 +1,35 @@
const program = require('commander');
const EmbarkController = require('./cmd_controller.js');
const i18n = require('../lib/core/i18n/i18n.js');
const utils = require('../lib/utils/utils.js');
let embark = new EmbarkController;
// set PWD to process.cwd() since Windows doesn't have a value for PWD
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
// set the anchor for embark's fs.dappPath()
if (!process.env.DAPP_PATH) {
process.env.DAPP_PATH = process.env.PWD;
}
// set the anchor for embark's fs.embarkPath()
if (!process.env.EMBARK_PATH) {
process.env.EMBARK_PATH = utils.joinPath(__dirname, '..');
}
// NOTE: setting NODE_PATH at runtime won't effect lookup behavior in the
// current process, but will take effect in child processes; this enables
// lookup of *global* embark's own node_modules from within dapp scripts (such
// as an ejected webpack.config.js), making embark's dependencies trasitive
// dependencies of a dapp without the dapp explicitly specifying embark as a
// dependency in the dapp's package.json
process.env.NODE_PATH = utils.joinPath(process.env.EMBARK_PATH, 'node_modules')
+ (process.env.NODE_PATH ? require('path').delimiter : '')
+ (process.env.NODE_PATH || '');
class Cmd {
constructor() {
program.version(embark.version);
@ -18,6 +45,7 @@ class Cmd {
this.simulator();
this.test();
this.reset();
this.ejectWebpack();
this.graph();
this.upload();
this.versionCmd();
@ -99,6 +127,7 @@ class Cmd {
.option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc'))
.option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug')
.option('--locale [locale]', __('language to use (default: en)'))
.option('--pipeline [pipeline]', __('webpack config to use (default: production)'))
.description(__('deploy and build dapp at ') + 'dist/ (default: development)')
.action(function (env, _options) {
i18n.setOrDetectLocale(_options.locale);
@ -107,6 +136,7 @@ class Cmd {
_options.logLevel = _options.loglevel; // fix casing
_options.onlyCompile = _options.contracts;
_options.client = _options.client || 'geth';
_options.webpackConfigName = _options.pipeline || 'production';
embark.build(_options);
});
}
@ -123,6 +153,7 @@ class Cmd {
.option('--logfile [logfile]', __('filename to output logs (default: %s)', 'none'))
.option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug')
.option('--locale [locale]', __('language to use (default: en)'))
.option('--pipeline [pipeline]', __('webpack config to use (default: development)'))
.description(__('run dapp (default: %s)', 'development'))
.action(function (env, options) {
i18n.setOrDetectLocale(options.locale);
@ -135,7 +166,8 @@ class Cmd {
runWebserver: !options.noserver,
useDashboard: !options.nodashboard,
logFile: options.logfile,
logLevel: options.loglevel
logLevel: options.loglevel,
webpackConfigName: options.pipeline || 'development'
});
});
}
@ -147,6 +179,7 @@ class Cmd {
.option('--logfile [logfile]', __('filename to output logs (default: %s)', 'none'))
.option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug')
.option('--locale [locale]', __('language to use (default: en)'))
.option('--pipeline [pipeline]', __('webpack config to use (default: development)'))
.description(__('Start the Embark console'))
.action(function (env, options) {
i18n.setOrDetectLocale(options.locale);
@ -155,7 +188,8 @@ class Cmd {
client: options.client || 'geth',
locale: options.locale,
logFile: options.logfile,
logLevel: options.loglevel
logLevel: options.loglevel,
webpackConfigName: options.pipeline || 'development'
});
});
}
@ -276,6 +310,15 @@ class Cmd {
});
}
ejectWebpack() {
program
.command('eject-webpack')
.description(__('copy the default webpack config into your dapp for customization'))
.action(function () {
embark.ejectWebpack();
});
}
versionCmd() {
program
.command('version')

View File

@ -5,11 +5,6 @@ require('colors');
let version = require('../package.json').version;
// Set PWD to CWD since Windows doesn't have a value for PWD
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
class EmbarkController {
constructor(options) {
@ -84,7 +79,8 @@ class EmbarkController {
logLevel: options.logLevel,
context: self.context,
useDashboard: options.useDashboard,
webServerConfig: webServerConfig
webServerConfig: webServerConfig,
webpackConfigName: options.webpackConfigName
});
engine.init();
@ -191,7 +187,8 @@ class EmbarkController {
logger: options.logger,
config: options.config,
plugins: options.plugins,
context: this.context
context: this.context,
webpackConfigName: options.webpackConfigName
});
engine.init();
@ -259,7 +256,8 @@ class EmbarkController {
logFile: options.logFile,
logLevel: options.logLevel,
context: this.context,
ipcRole: 'client'
ipcRole: 'client',
webpackConfigName: options.webpackConfigName
});
engine.init();
async.waterfall([
@ -404,10 +402,33 @@ class EmbarkController {
var fs = require('../lib/core/fs.js');
fs.removeSync('./chains.json');
fs.removeSync('.embark/');
fs.removeSync('node_modules/.cache');
fs.removeSync('dist/');
console.log(__("reset done!").green);
}
ejectWebpack() {
var fs = require('../lib/core/fs.js');
var dappConfig = fs.dappPath('webpack.config.js');
var embarkConfig = fs.embarkPath('lib/pipeline', 'webpack.config.js');
let ext = 1;
let dappConfigOld = dappConfig;
while (fs.existsSync(dappConfigOld)) {
dappConfigOld = dappConfig + `.${ext}`;
ext++;
}
if (dappConfigOld !== dappConfig) {
fs.copySync(dappConfig, dappConfigOld);
console.warn(`${dappConfig}`.yellow);
console.warn(__('copied to').dim.yellow);
console.warn(`${dappConfigOld}\n`.yellow);
}
fs.copySync(embarkConfig, dappConfig);
console.log(`${embarkConfig}`.green);
console.log(__('copied to').dim.green);
console.log(`${dappConfig}`.green);
}
upload(options) {
this.context = options.context || [constants.contexts.upload, constants.contexts.build];

View File

@ -123,11 +123,11 @@ Config.prototype._updateBlockchainCors = function(){
}
let cors = corsParts.join(',');
if(blockchainConfig.rpcCorsDomain === 'auto'){
if(blockchainConfig.rpcCorsDomain === 'auto'){
if(cors.length) blockchainConfig.rpcCorsDomain = cors;
else blockchainConfig.rpcCorsDomain = '';
}
if(blockchainConfig.wsOrigins === 'auto'){
if(blockchainConfig.wsOrigins === 'auto'){
if(cors.length) blockchainConfig.wsOrigins = cors;
else blockchainConfig.wsOrigins = '';
}
@ -169,7 +169,7 @@ Config.prototype._getFileOrOject = function(object, filePath, property) {
if (typeof (this.configDir) === 'object') {
return this.configDir[property];
}
return this.configDir + filePath;
return utils.joinPath(this.configDir, filePath);
};
Config.prototype.loadBlockchainConfigFile = function() {

View File

@ -18,6 +18,7 @@ class Engine {
this.useDashboard = options.useDashboard;
this.webServerConfig = options.webServerConfig;
this.ipcRole = options.ipcRole;
this.webpackConfigName = options.webpackConfigName;
}
init(_options) {
@ -102,7 +103,8 @@ class Engine {
assetFiles: this.config.assetFiles,
events: this.events,
logger: this.logger,
plugins: this.plugins
plugins: this.plugins,
webpackConfigName: this.webpackConfigName
});
this.events.on('code-generator-ready', function () {
self.events.request('code', function (abi, contractsJSON) {

View File

@ -77,13 +77,21 @@ function removeSync() {
return fs.removeSync.apply(fs.removeSync, arguments);
}
// returns embarks root directory
function embarkPath(fileOrDir) {
return utils.joinPath(__dirname, '/../../', fileOrDir);
function anchoredPath(envAnchor, ...args) {
const anchor = process.env[envAnchor];
if (!anchor) {
console.error(`process.env.${envAnchor} was not set`.bold.red);
process.exit(1);
}
return utils.joinPath(anchor, ...args);
}
function embarkPath() {
return anchoredPath('EMBARK_PATH', ...arguments);
}
function dappPath() {
return utils.joinPath(utils.pwd(), ...arguments);
return anchoredPath('DAPP_PATH', ...arguments);
}
function createWriteStream() {

View File

@ -1,6 +1,5 @@
const async = require('async');
var Plugin = require('./plugin.js');
var utils = require('../utils/utils.js');
var fs = require('../core/fs.js');
var Plugins = function(options) {
@ -75,7 +74,7 @@ Plugins.prototype.loadInternalPlugin = function(pluginName, pluginConfig) {
};
Plugins.prototype.loadPlugin = function(pluginName, pluginConfig) {
var pluginPath = utils.joinPath(utils.pwd(), 'node_modules', pluginName);
var pluginPath = fs.dappPath('node_modules', pluginName);
var plugin = require(pluginPath);
var pluginWrapper = new Plugin({

View File

@ -5,11 +5,6 @@ process.on('uncaughtException', function(e){
const constants = require('../../constants');
const Events = require('./eventsWrapper');
// Set PWD to CWD since Windows doesn't have a value for PWD
if (!process.env.PWD) {
process.env.PWD = process.cwd();
}
class ProcessWrapper {
/**

View File

@ -14,6 +14,7 @@ class Pipeline {
this.events = options.events;
this.logger = options.logger;
this.plugins = options.plugins;
this.webpackConfigName = options.webpackConfigName;
this.pipelinePlugins = this.plugins.getPluginsFor('pipeline');
}
@ -30,7 +31,7 @@ class Pipeline {
function createPlaceholderPage(next){
self.events.request('embark-building-placeholder', (html) => {
fs.mkdirpSync(self.buildDir); // create dist/ folder if not already exists
fs.writeFile(self.buildDir + 'index.html', html, next);
fs.writeFile(utils.joinPath(self.buildDir, 'index.html'), html, next);
});
},
function buildTheContracts(next) {
@ -51,7 +52,7 @@ class Pipeline {
next();
},
function writeContracts(next) {
function writeContracts(next) {
self.events.request('contracts:list', (_err, contracts) => {
// ensure the .embark/contracts directory exists (create if not exists)
fs.mkdirp(fs.dappPath(".embark/contracts", ''), (err) => {
@ -75,72 +76,63 @@ class Pipeline {
if(idx < contracts.length - 1) importsHelperFile.write(',\n'); // add a comma if we have more contracts to add
});
}, function(){
importsHelperFile.write('\n}'); // close the module.exports = {}
importsHelperFile.write('\n}'); // close the module.exports = {}
importsHelperFile.close(next); // close the write stream
});
});
});
},
function runWebpack(next) {
self.logger.info(__(`running webpack with '${self.webpackConfigName}' config...`));
Object.keys(self.assetFiles)
.filter(key => key.match(/\.js?$/))
.forEach(key => {
self.logger.info(__("writing file") + " " + (utils.joinPath(self.buildDir, key)).bold.dim);
});
let built = false;
const webpackProcess = new ProcessLauncher({
modulePath: utils.joinPath(__dirname, 'webpackProcess.js'),
logger: self.logger,
events: self.events,
exitCallback: function (code) {
if (!built) {
return next(`Webpack build exited with code ${code} before the process finished`);
}
if (code) {
self.logger.error(__('Webpack build process exited with code ', code));
}
}
});
webpackProcess.send({action: constants.pipeline.init, options: {webpackConfigName: self.webpackConfigName}});
webpackProcess.send({action: constants.pipeline.build, assets: self.assetFiles, importsList});
webpackProcess.once('result', constants.pipeline.built, (msg) => {
built = true;
webpackProcess.kill();
return next(msg.error);
});
},
function assetFileWrite(next) {
async.eachOf(self.assetFiles, function (files, targetFile, cb) {
async.map(files,
async.eachOf(
// assetFileWrite should not process .js files
Object.keys(self.assetFiles)
.filter(key => !key.match(/\.js?$/))
.reduce((obj, key) => {
obj[key] = self.assetFiles[key];
return obj;
}, {}),
function (files, targetFile, cb) {
const isDir = targetFile.slice(-1) === '/' || targetFile.slice(-1) === '\\' || targetFile.indexOf('.') === -1;
// if it's not a directory
if (!isDir) {
self.logger.info(__("writing file") + " " + (utils.joinPath(self.buildDir, targetFile)).bold.dim);
}
async.map(
files,
function (file, fileCb) {
self.logger.trace("reading " + file.filename);
// Not a JS file
if (file.filename.indexOf('.js') < 0) {
return file.content(function (fileContent) {
self.runPlugins(file, fileContent, fileCb);
});
}
// JS files
async.waterfall([
function runWebpack(next) {
let built = false;
const webpackProcess = new ProcessLauncher({
modulePath: utils.joinPath(__dirname, 'webpackProcess.js'),
logger: self.logger,
events: self.events,
exitCallback: function (code) {
if (!built) {
return next(`File building of ${file.filename} exited with code ${code} before the process finished`);
}
if (code) {
self.logger(__('File building process exited with code ', code));
}
}
});
webpackProcess.send({action: constants.pipeline.init, options: {env: self.env}});
webpackProcess.send({action: constants.pipeline.build, file, importsList});
webpackProcess.once('result', constants.pipeline.built, (msg) => {
built = true;
webpackProcess.kill();
return next(msg.error);
});
},
function readFile(next) {
fs.readFile('./.embark/' + file.filename, (err, data) => {
if (err) {
return next(err);
}
next(null, data.toString());
});
},
function runPluginsOnContent(fileContent, next) {
self.runPlugins(file, fileContent, next);
}
], function (err, contentFile) {
if (err) {
self.logger.error(err.message || err);
return fileCb(err);
}
fileCb(null, contentFile);
return file.content(function (fileContent) {
self.runPlugins(file, fileContent, fileCb);
});
},
function (err, contentFiles) {
@ -148,22 +140,22 @@ class Pipeline {
self.logger.error(__('errors found while generating') + ' ' + targetFile);
}
let dir = targetFile.split('/').slice(0, -1).join('/');
self.logger.trace("creating dir " + self.buildDir + dir);
fs.mkdirpSync(self.buildDir + dir);
self.logger.trace("creating dir " + utils.joinPath(self.buildDir, dir));
fs.mkdirpSync(utils.joinPath(self.buildDir, dir));
// if it's a directory
if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
if (isDir) {
let targetDir = targetFile;
if (targetDir.slice(-1) !== '/') {
targetDir = targetDir + '/';
}
async.each(contentFiles, function (file, mapCb) {
async.each(contentFiles, function (file, eachCb) {
let filename = file.filename.replace(file.basedir + '/', '');
self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);
self.logger.info("writing file " + (utils.joinPath(self.buildDir, targetDir, filename)).bold.dim);
fs.copy(file.path, self.buildDir + targetDir + filename, {overwrite: true}, mapCb);
fs.copy(file.path, utils.joinPath(self.buildDir, targetDir, filename), {overwrite: true}, eachCb);
}, cb);
return;
}
@ -175,20 +167,20 @@ class Pipeline {
return file.content;
}).join("\n");
self.logger.info(__("writing file") + " " + (self.buildDir + targetFile).bold.dim);
if(new RegExp(/^index.html?/i).test(targetFile)){
targetFile = targetFile.replace('index', 'index-temp');
placeholderPage = targetFile;
}
fs.writeFile(self.buildDir + targetFile, content, cb);
fs.writeFile(utils.joinPath(self.buildDir, targetFile), content, cb);
}
);
},
next);
next
);
},
function removePlaceholderPage(next){
let placeholderFile = self.buildDir + placeholderPage;
fs.access(self.buildDir + placeholderPage, (err) => {
let placeholderFile = utils.joinPath(self.buildDir, placeholderPage);
fs.access(utils.joinPath(self.buildDir, placeholderPage), (err) => {
if (err) return next(); // index-temp doesn't exist, do nothing
// rename index-temp.htm/l to index.htm/l, effectively replacing our placeholder page
@ -204,7 +196,8 @@ class Pipeline {
if (self.pipelinePlugins.length <= 0) {
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
}
async.eachSeries(self.pipelinePlugins,
async.eachSeries(
self.pipelinePlugins,
function(plugin, pluginCB) {
if (file.options && file.options.skipPipeline) {
return pluginCB();

View File

@ -0,0 +1,176 @@
// some packages, plugins, and presets referenced/required in this webpack
// config are deps of embark and will be transitive dapp deps unless specified
// in the dapp's own package.json
// embark modifies process.env.NODE_PATH so that when running dapp scripts in
// embark's child processes, embark's own node_modules directory will be
// searched by node's require(); however, webpack and babel do not directly
// support NODE_PATH, so modules such as babel plugins and presets must be
// resolved with require.resolve(); that is only necessary if a plugin/preset
// is in embark's node_modules vs. the dapp's node_modules
const cloneDeep = require('lodash.clonedeep');
const CompressionPlugin = require('compression-webpack-plugin');
const glob = require('glob');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const path = require('path');
const dappPath = process.env.DAPP_PATH;
const embarkPath = process.env.EMBARK_PATH;
const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json'));
const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json'));
const embarkNodeModules = path.join(embarkPath, 'node_modules');
const embarkJson = require(path.join(dappPath, 'embark.json'));
const buildDir = path.join(dappPath, embarkJson.buildDir);
// it's important to `embark reset` if a pkg version is specified in
// embark.json and changed/removed later, otherwise pkg resolution may behave
// unexpectedly
let versions;
try {
versions = glob.sync(path.join(dappPath, '.embark/versions/*/*'));
} catch (e) {
versions = [];
}
const entry = Object.keys(embarkAssets)
.filter(key => key.match(/\.js?$/))
.reduce((obj, key) => {
// webpack entry paths should start with './' if they're relative to the
// webpack context; embark.json "app" keys correspond to lists of .js
// source paths relative to the top-level dapp dir and may be missing the
// leading './'
obj[key] = embarkAssets[key]
.map(file => {
let file_path = file.path;
if (!file.path.match(/^\.\//)) {
file_path = './' + file_path;
}
return file_path;
});
return obj;
}, {});
function resolve(pkgName) {
if (Array.isArray(pkgName)) {
const _pkgName = pkgName[0];
pkgName[0] = require.resolve(_pkgName);
return pkgName;
}
return require.resolve(pkgName);
}
// base config
// -----------------------------------------------------------------------------
const base = {
context: dappPath,
entry: entry,
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: /\.jsx?$/,
loader: 'babel-loader',
exclude: /(node_modules|bower_components|\.embark[\\/]versions)/,
options: {
plugins: [
[
'babel-plugin-module-resolver', {
'alias': embarkAliases
}
],
[
'@babel/plugin-transform-runtime', {
corejs: 2,
useESModules: true
}
]
].map(resolve),
presets: [
[
'@babel/preset-env', {
modules: false,
targets: {
browsers: ['last 1 version', 'not dead', '> 0.2%']
}
}
],
'@babel/preset-react'
].map(resolve)
}
}
]
},
output: {
filename: (chunkData) => chunkData.chunk.name,
// globalObject workaround for node-compatible UMD builds with webpack 4
// see: https://github.com/webpack/webpack/issues/6522#issuecomment-371120689
globalObject: 'typeof self !== \'undefined\' ? self : this',
libraryTarget: 'umd',
path: buildDir
},
plugins: [new HardSourceWebpackPlugin()],
// profiling and generating verbose stats increases build time; if stats
// are generated embark will write the output to:
// path.join(dappPath, '.embark/stats.[json,report]')
// to visualize the stats info in a browser run:
// npx webpack-bundle-analyzer .embark/stats.json <buildDir>
profile: true, stats: 'verbose',
resolve: {
alias: embarkAliases,
modules: [
...versions,
'node_modules',
embarkNodeModules
]
},
resolveLoader: {
modules: [
'node_modules',
embarkNodeModules
]
}
};
// development config
// -----------------------------------------------------------------------------
const development = cloneDeep(base);
// full source maps increase build time but are useful during dapp development
development.devtool = 'source-map';
development.mode = 'development';
// alternatively:
// development.mode = 'none';
development.name = 'development';
const devBabelLoader = development.module.rules[3];
devBabelLoader.options.compact = false;
// production config
// -----------------------------------------------------------------------------
const production = cloneDeep(base);
production.mode = 'production';
production.name = 'production';
production.plugins.push(new CompressionPlugin());
// export a list of named configs
// -----------------------------------------------------------------------------
module.exports = [
development,
production
];

View File

@ -1,208 +1,104 @@
const async = require('async');
const webpack = require('webpack');
const utils = require('../utils/utils');
const fs = require('../core/fs');
const constants = require('../constants');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const fs = require('../core/fs');
const ProcessWrapper = require('../core/processes/processWrapper');
const path = require('path');
const glob = require('glob');
const webpack = require('webpack');
const writeFile = require('util').promisify(require('fs').writeFile);
const {errorMessage} = require('../utils/utils');
let webpackProcess;
class WebpackProcess extends ProcessWrapper {
constructor(options) {
super(options);
this.env = options.env;
this.webpackConfigName = options.webpackConfigName;
}
build(file, importsList, callback) {
const self = this;
let realCwd;
async.waterfall([
function changeCwd(next) {
realCwd = utils.pwd();
process.chdir(fs.embarkPath(''));
next();
},
function runWebpack(next) {
self.webpackRun(file.filename, {}, true, importsList, true, realCwd, next);
},
function changeCwdBack(next) {
process.chdir(realCwd);
next();
}
], (err) => {
process.chdir(realCwd);
callback(err);
});
async build(assets, importsList, callback) {
try {
await this.webpackRun(assets, importsList, callback);
} catch (e) {
callback(errorMessage(e));
}
}
webpackRun(filename, options, includeModules, importsList, detectErrors, realCwd, callback) {
const self = this;
glob(fs.dappPath('.embark/versions/*/*'), (err, files) => {
let versions;
if (err) {
console.error(err);
versions = [];
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)
);
} catch (e) {
return callback(errorMessage(e));
}
const dappConfigPath = fs.dappPath('webpack.config.js');
const defaultConfigPath = fs.embarkPath('lib/pipeline', 'webpack.config.js');
let config, configPath;
try {
if (fs.existsSync(dappConfigPath)) {
configPath = dappConfigPath;
delete require.cache[configPath];
} else {
versions = files;
configPath = defaultConfigPath;
}
let defaultOptions = {
mode: self.env === 'production' ? 'production' : 'none',
// devtool: self.env === 'development' ? 'source-map' : false,
// pipeline would need to copy .map files to dist/ target dir
// note: generating full source maps ('source-map') roughly doubles build time
entry: fs.dappPath(filename),
output: {
globalObject: 'typeof self !== \'undefined\' ? self : this',
libraryExport: 'default',
libraryTarget: 'umd',
path: fs.dappPath('.embark'),
filename: filename,
umdNamedDefine: true
},
// 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()
}
}),
new HardSourceWebpackPlugin.ExcludeModulePlugin(
[{test: /app[\\/]|contracts[\\/]/}]
)
]
};
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;
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));
}
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();
}//,
// function writeStatsReport(next) {
// if (detectErrors) {
// self._log('info', 'writing file '+ ('.embark/stats.report').bold.dim);
// }
// fs.writeFile(
// path.join(fs.dappPath('.embark'), 'stats.report'),
// stats.toString(webpackOptions.stats),
// next
// );
// },
// function writeStatsJSON(next) {
// if (detectErrors) {
// self._log('info','writing file '+ ('.embark/stats.json').bold.dim);
// }
// fs.writeFile(
// path.join(fs.dappPath('.embark'), 'stats.json'),
// JSON.stringify(stats.toJson(webpackOptions.stats)),
// next
// );
// }
// note: to visualize the stats info in a browser, do...
// `npx webpack-bundle-analyzer <dapp_dir>/.embark/stats.json`
], (err) => {
callback(err);
});
});
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));
}
});
}
}
@ -214,7 +110,7 @@ process.on('message', (msg) => {
}
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});
});
}

View File

@ -200,10 +200,6 @@ function proposeAlternative(word, _dictionary, _exceptions) {
return propose(word, dictionary, {threshold: 0.3});
}
function pwd() {
return process.env.PWD || process.cwd();
}
function getExternalContractUrl(file) {
const constants = require('../constants');
let url;
@ -462,6 +458,15 @@ function interceptLogs(consoleContext, logger) {
};
}
function errorMessage(e) {
if (typeof e === 'string') {
return e;
} else if (e && e.message) {
return e.message;
}
return e;
}
module.exports = {
joinPath,
dirname,
@ -489,7 +494,6 @@ module.exports = {
extractTar,
extractZip,
proposeAlternative,
pwd: pwd,
getExternalContractUrl,
toChecksumAddress,
sha3,
@ -504,5 +508,6 @@ module.exports = {
groupBy,
sample,
last,
interceptLogs
interceptLogs,
errorMessage
};

99
package-lock.json generated
View File

@ -1313,66 +1313,16 @@
"util.promisify": "^1.0.0"
}
},
"babel-plugin-webpack-aliases": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/babel-plugin-webpack-aliases/-/babel-plugin-webpack-aliases-1.1.3.tgz",
"integrity": "sha1-+7oor/c+SDc4949wRMGDrSF5toA=",
"babel-plugin-module-resolver": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.1.1.tgz",
"integrity": "sha512-1Q77Al4ydp6nYApJ7sQ2fmgz30WuQgJZegIYuyOdbdpxenB/bSezQ3hDPsumIXGlUS4vUIv+EwFjzzXZNWtARw==",
"requires": {
"babel-types": "^6.5.2",
"find-up": "1.1.2"
},
"dependencies": {
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
"requires": {
"path-exists": "^2.0.0",
"pinkie-promise": "^2.0.0"
}
},
"path-exists": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
"requires": {
"pinkie-promise": "^2.0.0"
}
}
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
}
}
},
"babel-types": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
"requires": {
"babel-runtime": "^6.26.0",
"esutils": "^2.0.2",
"lodash": "^4.17.4",
"to-fast-properties": "^1.0.3"
},
"dependencies": {
"to-fast-properties": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
}
"find-babel-config": "^1.1.0",
"glob": "^7.1.2",
"pkg-up": "^2.0.0",
"reselect": "^3.0.1",
"resolve": "^1.4.0"
}
},
"balanced-match": {
@ -2162,6 +2112,18 @@
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
},
"compression-webpack-plugin": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-1.1.11.tgz",
"integrity": "sha512-ZVWKrTQhtOP7rDx3M/koXTnRm/iwcYbuCdV+i4lZfAIe32Mov7vUVM0+8Vpz4q0xH+TBUZxq+rM8nhtkDH50YQ==",
"requires": {
"cacache": "^10.0.1",
"find-cache-dir": "^1.0.0",
"neo-async": "^2.5.0",
"serialize-javascript": "^1.4.0",
"webpack-sources": "^1.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -3631,6 +3593,15 @@
}
}
},
"find-babel-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.1.0.tgz",
"integrity": "sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U=",
"requires": {
"json5": "^0.5.1",
"path-exists": "^3.0.0"
}
},
"find-cache-dir": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
@ -5595,6 +5566,11 @@
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -7856,6 +7832,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"reselect": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
"integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc="
},
"resolve": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",

View File

@ -29,12 +29,13 @@
"ascii-table": "0.0.9",
"async": "^2.0.1",
"babel-loader": "8.0.0-beta.4",
"babel-plugin-webpack-aliases": "^1.1.3",
"babel-plugin-module-resolver": "^3.1.1",
"bip39": "^2.5.0",
"chokidar": "^2.0.3",
"clone-deep": "^4.0.0",
"colors": "^1.1.2",
"commander": "^2.15.1",
"compression-webpack-plugin": "^1.1.11",
"css-loader": "^0.28.11",
"decompress": "^4.2.0",
"deep-equal": "^1.0.1",
@ -57,6 +58,7 @@
"ipfs-api": "17.2.4",
"is-valid-domain": "0.0.5",
"live-plugin-manager-git-fix": "^0.12.1",
"lodash.clonedeep": "^4.5.0",
"merge": "^1.2.0",
"mocha": "^5.2.0",
"multihashes": "^0.4.13",

View File

@ -1 +0,0 @@
{}