2018-08-20 19:19:26 +00:00
|
|
|
// some packages, plugins, and presets referenced/required in this webpack
|
2018-08-16 20:49:19 +00:00
|
|
|
// config are deps of embark and will be transitive dapp deps unless specified
|
2018-08-20 19:19:26 +00:00
|
|
|
// in the dapp's own package.json
|
2018-08-16 20:49:19 +00:00
|
|
|
|
2018-08-20 19:19:26 +00:00
|
|
|
// 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
|
2018-08-17 17:32:58 +00:00
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
const cloneDeep = require('lodash.clonedeep');
|
2018-08-28 20:50:40 +00:00
|
|
|
// const CompressionPlugin = require('compression-webpack-plugin');
|
2018-08-16 20:49:19 +00:00
|
|
|
const glob = require('glob');
|
|
|
|
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
|
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
const dappPath = process.env.DAPP_PATH;
|
2018-08-17 17:34:20 +00:00
|
|
|
const embarkPath = process.env.EMBARK_PATH;
|
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json'));
|
|
|
|
const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json'));
|
2018-08-17 21:45:35 +00:00
|
|
|
const embarkJson = require(path.join(dappPath, 'embark.json'));
|
2018-10-02 16:30:06 +00:00
|
|
|
const embarkNodeModules = path.join(embarkPath, 'node_modules');
|
|
|
|
const embarkPipeline = require(path.join(dappPath, '.embark/embark-pipeline.json'));
|
2018-08-16 20:49:19 +00:00
|
|
|
|
2018-08-17 22:55:59 +00:00
|
|
|
const buildDir = path.join(dappPath, embarkJson.buildDir);
|
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
// it's important to `embark reset` if a pkg version is specified in
|
|
|
|
// embark.json and changed/removed later, otherwise pkg resolution may behave
|
2018-08-20 19:19:26 +00:00
|
|
|
// unexpectedly
|
2018-08-16 20:49:19 +00:00
|
|
|
let versions;
|
|
|
|
try {
|
|
|
|
versions = glob.sync(path.join(dappPath, '.embark/versions/*/*'));
|
|
|
|
} catch (e) {
|
|
|
|
versions = [];
|
|
|
|
}
|
|
|
|
|
2018-08-17 21:45:47 +00:00
|
|
|
const entry = Object.keys(embarkAssets)
|
2018-09-05 21:49:26 +00:00
|
|
|
.filter(key => key.match(/\.js$/))
|
2018-08-20 15:28:43 +00:00
|
|
|
.reduce((obj, key) => {
|
2018-08-20 18:52:48 +00:00
|
|
|
// 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 './'
|
2018-08-20 15:28:43 +00:00
|
|
|
obj[key] = embarkAssets[key]
|
|
|
|
.map(file => {
|
|
|
|
let file_path = file.path;
|
|
|
|
if (!file.path.match(/^\.\//)) {
|
|
|
|
file_path = './' + file_path;
|
|
|
|
}
|
|
|
|
return file_path;
|
|
|
|
});
|
|
|
|
return obj;
|
|
|
|
}, {});
|
2018-08-16 20:49:19 +00:00
|
|
|
|
2018-08-19 00:55:34 +00:00
|
|
|
function resolve(pkgName) {
|
|
|
|
if (Array.isArray(pkgName)) {
|
|
|
|
const _pkgName = pkgName[0];
|
|
|
|
pkgName[0] = require.resolve(_pkgName);
|
|
|
|
return pkgName;
|
|
|
|
}
|
2018-08-20 18:57:04 +00:00
|
|
|
return require.resolve(pkgName);
|
2018-08-19 00:55:34 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
// base config
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2018-10-02 00:51:01 +00:00
|
|
|
// order and options of babel plugins and presets adapted from babel-preset-react-app:
|
2018-10-04 18:17:18 +00:00
|
|
|
// see: https://github.com/facebook/create-react-app/tree/v2.0.4/packages/babel-preset-react-app
|
2018-10-02 00:51:01 +00:00
|
|
|
// + babel plugins run before babel presets.
|
|
|
|
// + babel plugin ordering is first to last.
|
|
|
|
// + babel preset ordering is reversed (last to first).
|
2018-10-01 23:36:46 +00:00
|
|
|
// see: https://babeljs.io/docs/en/plugins#plugin-ordering
|
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
const base = {
|
|
|
|
context: dappPath,
|
|
|
|
entry: entry,
|
|
|
|
module: {
|
|
|
|
rules: [
|
|
|
|
{
|
2018-10-02 00:16:32 +00:00
|
|
|
test: /\.scss$/,
|
|
|
|
use: [
|
|
|
|
'style-loader',
|
|
|
|
'css-loader',
|
|
|
|
'sass-loader'
|
|
|
|
]
|
2018-08-16 20:49:19 +00:00
|
|
|
},
|
|
|
|
{
|
2018-10-02 00:16:56 +00:00
|
|
|
test: /\.css$/,
|
|
|
|
use: [
|
|
|
|
'style-loader',
|
|
|
|
'css-loader'
|
|
|
|
]
|
2018-08-16 20:49:19 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
|
|
|
|
loader: 'url-loader?limit=100000'
|
|
|
|
},
|
|
|
|
{
|
2018-08-16 21:49:32 +00:00
|
|
|
test: /\.jsx?$/,
|
2018-08-16 20:49:19 +00:00
|
|
|
loader: 'babel-loader',
|
|
|
|
exclude: /(node_modules|bower_components|\.embark[\\/]versions)/,
|
|
|
|
options: {
|
2018-10-02 00:17:20 +00:00
|
|
|
cacheDirectory: true,
|
2018-10-03 19:57:26 +00:00
|
|
|
cacheCompression: false,
|
2018-10-03 19:53:40 +00:00
|
|
|
customize: path.join(__dirname, 'babel-loader-overrides.js'),
|
2018-08-16 20:49:19 +00:00
|
|
|
plugins: [
|
|
|
|
[
|
2018-08-19 00:55:34 +00:00
|
|
|
'babel-plugin-module-resolver', {
|
2018-10-02 00:18:07 +00:00
|
|
|
alias: embarkAliases
|
2018-08-16 20:49:19 +00:00
|
|
|
}
|
|
|
|
],
|
2018-10-02 00:19:14 +00:00
|
|
|
'babel-plugin-macros',
|
|
|
|
'@babel/plugin-transform-destructuring',
|
|
|
|
[
|
|
|
|
'@babel/plugin-proposal-class-properties', {
|
|
|
|
loose: true
|
|
|
|
}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'@babel/plugin-proposal-object-rest-spread', {
|
|
|
|
useBuiltIns: true
|
|
|
|
}
|
|
|
|
],
|
2018-08-16 20:49:19 +00:00
|
|
|
[
|
2018-08-19 00:55:34 +00:00
|
|
|
'@babel/plugin-transform-runtime', {
|
2018-08-16 20:49:19 +00:00
|
|
|
corejs: 2,
|
|
|
|
useESModules: true
|
|
|
|
}
|
2018-10-02 00:19:14 +00:00
|
|
|
],
|
|
|
|
'@babel/plugin-syntax-dynamic-import'
|
2018-08-19 00:55:34 +00:00
|
|
|
].map(resolve),
|
2018-08-16 20:49:19 +00:00
|
|
|
presets: [
|
|
|
|
[
|
2018-08-19 00:55:34 +00:00
|
|
|
'@babel/preset-env', {
|
2018-10-04 18:17:53 +00:00
|
|
|
exclude: ['transform-typeof-symbol'],
|
2018-08-16 20:49:19 +00:00
|
|
|
modules: false,
|
|
|
|
targets: {
|
|
|
|
browsers: ['last 1 version', 'not dead', '> 0.2%']
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
2018-10-02 00:19:14 +00:00
|
|
|
[
|
|
|
|
'@babel/preset-react', {
|
|
|
|
useBuiltIns: true
|
|
|
|
}
|
|
|
|
]
|
2018-08-19 00:55:34 +00:00
|
|
|
].map(resolve)
|
2018-08-16 20:49:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
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',
|
2018-08-17 22:55:59 +00:00
|
|
|
path: buildDir
|
2018-08-16 20:49:19 +00:00
|
|
|
},
|
2018-08-17 22:14:28 +00:00
|
|
|
plugins: [new HardSourceWebpackPlugin()],
|
2018-08-16 20:49:19 +00:00
|
|
|
// 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:
|
2018-08-22 23:25:46 +00:00
|
|
|
// npx webpack-bundle-analyzer .embark/stats.json <buildDir>
|
2018-08-16 20:49:19 +00:00
|
|
|
profile: true, stats: 'verbose',
|
|
|
|
resolve: {
|
|
|
|
alias: embarkAliases,
|
2018-10-02 00:19:14 +00:00
|
|
|
extensions: [
|
|
|
|
// webpack defaults
|
|
|
|
// see: https://webpack.js.org/configuration/resolve/#resolve-extensions
|
|
|
|
'.wasm', '.mjs', '.js', '.json',
|
|
|
|
// additional extensions
|
|
|
|
'.jsx'
|
|
|
|
],
|
2018-08-16 20:49:19 +00:00
|
|
|
modules: [
|
|
|
|
...versions,
|
2018-08-17 17:34:20 +00:00
|
|
|
'node_modules',
|
2018-08-17 22:55:59 +00:00
|
|
|
embarkNodeModules
|
2018-08-16 20:49:19 +00:00
|
|
|
]
|
2018-08-17 17:34:20 +00:00
|
|
|
},
|
|
|
|
resolveLoader: {
|
|
|
|
modules: [
|
|
|
|
'node_modules',
|
2018-08-17 22:55:59 +00:00
|
|
|
embarkNodeModules
|
2018-08-17 22:14:28 +00:00
|
|
|
]
|
2018-08-16 20:49:19 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-10-02 00:19:14 +00:00
|
|
|
const baseBabelLoader = base.module.rules[3];
|
|
|
|
|
|
|
|
// Flow
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// should be false in configs that have isTypeScriptEnabled = true
|
2018-10-02 16:30:06 +00:00
|
|
|
const isFlowEnabled = !embarkPipeline.typescript;
|
2018-10-02 00:19:14 +00:00
|
|
|
if (isFlowEnabled) {
|
|
|
|
// position @babel/plugin-transform-flow-strip-types per babel-preset-react-app
|
|
|
|
baseBabelLoader.options.plugins.unshift(
|
|
|
|
require.resolve('@babel/plugin-transform-flow-strip-types')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-10-02 00:19:55 +00:00
|
|
|
// TypeScript
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// should be false in configs that have isFlowEnabled = true
|
2018-10-02 16:30:06 +00:00
|
|
|
const isTypeScriptEnabled = !!embarkPipeline.typescript;
|
2018-10-02 00:19:55 +00:00
|
|
|
if (isTypeScriptEnabled) {
|
|
|
|
// position @babel/preset-typescript as the last preset (runs first)
|
|
|
|
// see: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/
|
|
|
|
baseBabelLoader.options.presets.push(
|
|
|
|
require.resolve('@babel/preset-typescript')
|
|
|
|
);
|
|
|
|
// additional extensions
|
2018-10-02 18:03:19 +00:00
|
|
|
baseBabelLoader.test = /\.(js|ts)x?$/;
|
2018-10-02 00:19:55 +00:00
|
|
|
base.resolve.extensions.push('.ts', '.tsx');
|
|
|
|
}
|
|
|
|
|
2018-10-02 00:20:10 +00:00
|
|
|
if (isFlowEnabled && isTypeScriptEnabled) {
|
|
|
|
throw new Error('isFlowEnabled and isTypeScriptEnabled cannot both be true');
|
|
|
|
}
|
|
|
|
|
2018-08-16 20:49:19 +00:00
|
|
|
// development config
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const development = cloneDeep(base);
|
|
|
|
// full source maps increase build time but are useful during dapp development
|
2018-08-17 21:46:16 +00:00
|
|
|
development.devtool = 'source-map';
|
2018-08-16 20:49:19 +00:00
|
|
|
development.mode = 'development';
|
2018-08-17 21:46:36 +00:00
|
|
|
// alternatively:
|
|
|
|
// development.mode = 'none';
|
2018-08-16 20:49:19 +00:00
|
|
|
development.name = 'development';
|
|
|
|
const devBabelLoader = development.module.rules[3];
|
|
|
|
devBabelLoader.options.compact = false;
|
2018-10-02 00:19:14 +00:00
|
|
|
// enable 'development' option for @babel/preset-react
|
|
|
|
const devPresetReact = devBabelLoader.options.presets[1];
|
|
|
|
const devPresetReactOptions = devPresetReact[1];
|
|
|
|
devPresetReactOptions.development = true;
|
2018-08-16 20:49:19 +00:00
|
|
|
|
|
|
|
// production config
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const production = cloneDeep(base);
|
|
|
|
production.mode = 'production';
|
|
|
|
production.name = 'production';
|
2018-10-02 00:19:14 +00:00
|
|
|
const prodBabelLoader = production.module.rules[3];
|
|
|
|
// position babel-plugin-transform-react-remove-prop-types per babel-preset-react-app
|
|
|
|
prodBabelLoader.options.plugins.splice(prodBabelLoader.length - 1, 0, [
|
|
|
|
require.resolve('babel-plugin-transform-react-remove-prop-types'),
|
|
|
|
{
|
|
|
|
removeImport: true
|
|
|
|
}
|
|
|
|
]);
|
2018-08-28 20:45:11 +00:00
|
|
|
// compression of webpack's JS output not enabled by default
|
|
|
|
// production.plugins.push(new CompressionPlugin());
|
2018-08-16 20:49:19 +00:00
|
|
|
|
|
|
|
// export a list of named configs
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
module.exports = [
|
|
|
|
development,
|
|
|
|
production
|
|
|
|
];
|