/ 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  ];