0

Im trying to create a production build of my code and have made a webpack.production.config.js file. When I run 'webpack -p', my bundle.js file size is reduced but my bundle.js.map file size is increased. Here is the code and respective outputs:

webpack.config.js:

const path = require("path"); //eslint-disable-line
const webpack = require('webpack');


module.exports = {
  context: __dirname,
  entry: "./frontend/index.jsx",
  output: {
    path: path.join(__dirname, 'assets', 'build'),
    filename: "bundle.js",
    devtoolModuleFilenameTemplate: '[resourcePath]',
    devtoolFallbackModuleFilenameTemplate: '[resourcePath]?[hash]'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true
  },
  module: {
    loaders: [
      {
        test: [/\.jsx?$/, /\.js?$/],
        exclude: /(node_modules|bower_components)/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'react']
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader'
      }
    ]
  },
  devtool: 'source-map',
  eslint: {
    configFile: './.eslintrc'
  },
  resolve: {
    extensions: ["", ".js", ".jsx" ]
  },
  watchOptions: {
    aggregateTimeout: 500,
    poll: 2000,
    ignored: /node_modules/
 }
};



11:22 $ webpack
Hash: 3eaf0c4ed8964deb6866
Version: webpack 1.13.3
Time: 5805ms
        Asset     Size  Chunks             Chunk Names
    bundle.js  2.16 MB       0  [emitted]  main
bundle.js.map  2.53 MB       0  [emitted]  main
    + 484 hidden modules

webpack.production.config.js:

const path = require("path"); //eslint-disable-line
const webpack = require('webpack');


module.exports = {
  context: __dirname,
  entry: "./frontend/index.jsx",
  output: {
    path: path.join(__dirname, 'assets', 'build'),
    filename: "bundle.js",
    devtoolModuleFilenameTemplate: '[resourcePath]',
    devtoolFallbackModuleFilenameTemplate: '[resourcePath]?[hash]'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true
  },
  module: {
    loaders: [
      {
        test: [/\.jsx?$/, /\.js?$/],
        exclude: /(node_modules|bower_components)/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'react']
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader'
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: true
      }
    })
  ],
  devtool: 'cheap-module-source-map',
  resolve: {
    extensions: ["", ".js", ".jsx" ]
  }
};


11:19 $ webpack -p
Hash: c40d4a49c049e8b5a525
Version: webpack 1.13.3
Time: 20990ms
        Asset     Size  Chunks             Chunk Names
    bundle.js   805 kB       0  [emitted]  main
bundle.js.map  5.55 MB       0  [emitted]  main
    + 484 hidden modules

Any idea why bundle.js.map increases so significantly and if this is a problem? I also get a bunch of warnings from Uglify.js that I've been told to ignore.

Thanks.

Kabir Nigam
  • 45
  • 2
  • 5

2 Answers2

2

I don't think this is a problem because source-maps are only used for debugging. Also they are only loaded when devtools are open. Performance impact of using css / javascript source-maps in production

Community
  • 1
  • 1
nlarche
  • 132
  • 7
0

In short it is better to add several plugins (see description at the end) and use section "optimization: {...}" in your webpack.config.js

I have webpack 6.0.1. Based on the documentation I tested, use the following configuration ideas for webpack.config.js. You can test your configuration against these settings:

//webpack.config.js
module.exports = {
  ...
  devtool: 'cheap-module-source-map',
  ...
  plugins : [
    ...
    new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.HashedModuleIdsPlugin({
      hashFunction: 'sha256',
      hashDigest: 'hex',
      hashDigestLength: 4
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
  ],

  ...

  optimization: {
    namedModules: false,
    namedChunks: false,
    nodeEnv: 'production',
    flagIncludedChunks: true,
    occurrenceOrder: true,
    sideEffects: true,
    usedExports: true,
    concatenateModules: true,
    splitChunks: {
      cacheGroups: {
        commons: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendor',
            chunks: 'all'
        }
      },
      minSize: 30000,
      maxAsyncRequests: 5,
      maxAsyncRequests: 3,      
    },
    noEmitOnErrors: true,
    minimize: true, 
    minimizer: [
      // we specify a custom UglifyJsPlugin here to get source maps in production
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        uglifyOptions: {
          compress: false,
          ecma: 6,
          mangle: true
        },
        sourceMap: true
      })
    ],
    removeAvailableModules: true,
    removeEmptyChunks: true,
    mergeDuplicateChunks: true,    
  },
...
}

Notes:

  1. webpack.optimize.ModuleConcatenationPlugin() - concatenate the scope of all your modules into one closure and allow for your code to have a faster execution time in the browser
  2. webpack.HashedModuleIdsPlugin() - cause hashes to be based on the relative path of the module, generating a four character string as the module id
  3. webpack.optimize.OccurrenceOrderPlugin() - vary the distribution of the ids to get the smallest id length for often used ids
  4. webpack.NoEmitOnErrorsPlugin() - skip the emitting phase whenever there are errors while compiling. This ensures that no assets are emitted that include errors
Roman
  • 19,236
  • 15
  • 93
  • 97