/ webpack.config.js
webpack.config.js
1 // some packages, plugins, and presets referenced/required in this webpack 2 // config are deps of embark and will be transitive dapp deps unless specified 3 // in the dapp's own package.json 4 5 // embark modifies process.env.NODE_PATH so that when running dapp scripts in 6 // embark's child processes, embark's own node_modules directory will be 7 // searched by node's require(); however, webpack and babel do not directly 8 // support NODE_PATH, so modules such as babel plugins and presets must be 9 // resolved with require.resolve(); that is only necessary if a plugin/preset 10 // is in embark's node_modules vs. the dapp's node_modules 11 12 const cloneDeep = require('lodash.clonedeep'); 13 // const CompressionPlugin = require('compression-webpack-plugin'); 14 const glob = require('glob'); 15 const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); 16 const path = require('path'); 17 18 const dappPath = process.env.DAPP_PATH; 19 const embarkPath = process.env.EMBARK_PATH; 20 21 const embarkAliases = require(path.join(dappPath, '.embark/embark-aliases.json')); 22 const embarkAssets = require(path.join(dappPath, '.embark/embark-assets.json')); 23 const embarkNodeModules = path.join(embarkPath, 'node_modules'); 24 const embarkJson = require(path.join(dappPath, 'embark.json')); 25 26 const buildDir = path.join(dappPath, embarkJson.buildDir); 27 28 // it's important to `embark reset` if a pkg version is specified in 29 // embark.json and changed/removed later, otherwise pkg resolution may behave 30 // unexpectedly 31 let versions; 32 try { 33 versions = glob.sync(path.join(dappPath, '.embark/versions/*/*')); 34 } catch (e) { 35 versions = []; 36 } 37 38 const entry = Object.keys(embarkAssets) 39 .filter(key => key.match(/\.js$/)) 40 .reduce((obj, key) => { 41 // webpack entry paths should start with './' if they're relative to the 42 // webpack context; embark.json "app" keys correspond to lists of .js 43 // source paths relative to the top-level dapp dir and may be missing the 44 // leading './' 45 obj[key] = embarkAssets[key] 46 .map(file => { 47 let file_path = file.path; 48 if (!file.path.match(/^\.\//)) { 49 file_path = './' + file_path; 50 } 51 return file_path; 52 }); 53 return obj; 54 }, {}); 55 56 function resolve(pkgName) { 57 if (Array.isArray(pkgName)) { 58 const _pkgName = pkgName[0]; 59 pkgName[0] = require.resolve(_pkgName); 60 return pkgName; 61 } 62 return require.resolve(pkgName); 63 } 64 65 // base config 66 // ----------------------------------------------------------------------------- 67 68 const base = { 69 context: dappPath, 70 entry: entry, 71 module: { 72 rules: [ 73 { 74 test: /\.css$/, 75 use: [{loader: 'style-loader'}, {loader: 'css-loader'}] 76 }, 77 { 78 test: /\.scss$/, 79 use: [{loader: 'style-loader'}, {loader: 'css-loader'}] 80 }, 81 { 82 test: /\.(png|woff|woff2|eot|ttf|svg)$/, 83 loader: 'url-loader?limit=100000' 84 }, 85 { 86 test: /\.(js|jsx|tsx|ts)$/, 87 loader: 'babel-loader', 88 exclude: /(node_modules|bower_components|\.embark[\\/]versions)/, 89 options: { 90 plugins: [ 91 [ 92 'babel-plugin-module-resolver', { 93 'alias': embarkAliases 94 } 95 ], 96 [ 97 '@babel/plugin-transform-runtime', { 98 corejs: 2, 99 useESModules: true 100 } 101 ] 102 ].map(resolve), 103 presets: [ 104 [ 105 '@babel/preset-env', { 106 modules: false, 107 targets: { 108 browsers: ['last 1 version', 'not dead', '> 0.2%'] 109 } 110 } 111 ], 112 '@babel/preset-react', 113 '@babel/preset-typescript' 114 ].map(resolve) 115 } 116 } 117 ] 118 }, 119 output: { 120 filename: (chunkData) => chunkData.chunk.name, 121 // globalObject workaround for node-compatible UMD builds with webpack 4 122 // see: https://github.com/webpack/webpack/issues/6522#issuecomment-371120689 123 globalObject: 'typeof self !== \'undefined\' ? self : this', 124 libraryTarget: 'umd', 125 path: buildDir 126 }, 127 plugins: [new HardSourceWebpackPlugin()], 128 // profiling and generating verbose stats increases build time; if stats 129 // are generated embark will write the output to: 130 // path.join(dappPath, '.embark/stats.[json,report]') 131 // to visualize the stats info in a browser run: 132 // npx webpack-bundle-analyzer .embark/stats.json <buildDir> 133 profile: true, stats: 'verbose', 134 resolve: { 135 alias: embarkAliases, 136 modules: [ 137 ...versions, 138 'node_modules', 139 embarkNodeModules 140 ] 141 }, 142 resolveLoader: { 143 modules: [ 144 'node_modules', 145 embarkNodeModules 146 ] 147 } 148 }; 149 150 // development config 151 // ----------------------------------------------------------------------------- 152 153 const development = cloneDeep(base); 154 // full source maps increase build time but are useful during dapp development 155 development.devtool = 'source-map'; 156 development.mode = 'development'; 157 // alternatively: 158 // development.mode = 'none'; 159 development.name = 'development'; 160 const devBabelLoader = development.module.rules[3]; 161 devBabelLoader.options.compact = false; 162 163 // production config 164 // ----------------------------------------------------------------------------- 165 166 const production = cloneDeep(base); 167 production.mode = 'production'; 168 production.name = 'production'; 169 // compression of webpack's JS output not enabled by default 170 // production.plugins.push(new CompressionPlugin()); 171 172 // export a list of named configs 173 // ----------------------------------------------------------------------------- 174 175 module.exports = [ 176 development, 177 production 178 ];