Just a small catalog of Webpack tips and tricks I've learned. These tricks work with Webpack v3 unless otherwise specified.
- Progress reporting
- Minification
- Multiple bundles
- Split app and vendor code
- Source maps (Webpack 1)
- Source maps (Webpack 2-3)
- Output CSS files
- Development mode
- Investigating bundle sizes
- Smaller React
- Smaller Lodash
- Requiring all files in a folder
- Clean up extract-text-webpack-plugin log
Invoke Webpack with:
--progress --colors
Invoke Webpack with -p for production builds. In Webpack 2, this also automatically sets process.env.NODE_ENV === 'production'.
webpack -p
Export multiple bundles by setting the output to [name].js. This example produces a.js and b.js.
module.exports = { entry: { a: './a', b: './b' }, output: { filename: '[name].js' } }
Concerned about duplication? Use the CommonsChunkPlugin to move the common parts into a new output file.
plugins: [ new webpack.optimize.CommonsChunkPlugin('init.js') ]
<script src='init.js'></script> <script src='a.js'></script>
Use CommonsChunkPlugin to move vendor code into vendor.js.
var webpack = require('webpack') module.exports = { entry: { app: './app.js', vendor: ['jquery', 'underscore', ...] }, output: { filename: '[name].js' }, plugins: [ new webpack.optimize.CommonsChunkPlugin('vendor') ] }
How this works:
- We make a
vendorentry point and load it with some libraries - CommonsChunkPlugin will remove these libraries from
app.js(because it appears in 2 bundles now) - CommonsChunkPlugin also moves the Webpack runtime into
vendor.js
Reference: Code splitting
The best source maps option is cheap-module-eval-source-map. This shows original source files in Chrome/Firefox dev tools. It's faster than source-map and eval-source-map.
// Webpack 1 only const DEBUG = process.env.NODE_ENV !== 'production' module.exports = { debug: DEBUG ? true : false, devtool: DEBUG ? 'cheap-module-eval-source-map' : 'hidden-source-map' }
Your files will now show up in Chrome Devtools as webpack:///foo.js?a93h. We want this to be cleaner like webpack:///path/to/foo.js.
output: { devtoolModuleFilenameTemplate: 'webpack:///[absolute-resource-path]' }
Reference: devtool documentation
The best source maps option is cheap-module-source-map. The cheap-module-eval-source-map strategy no longer shows correct traces in Chrome/Firefox.
// Webpack 2 only const DEBUG = process.env.NODE_ENV !== 'production' module.exports = { devtool: DEBUG ? 'cheap-module-source-map' : 'hidden-source-map' }
If you're using extract-text-webpack-plugin, use 'source-map' instead. CSS sourcemaps won't work otherwise.
// Only if you're using extract-text-webpack-plugin module.exports = { devtool: DEBUG ? 'source-map' : 'hidden-source-map' }
Your files will now show up in Chrome Devtools as webpack:///foo.js?a93h. We want this to be cleaner like webpack:///path/to/foo.js.
output: { devtoolModuleFilenameTemplate: 'webpack:///[absolute-resource-path]' }
Reference: devtool documentation
This is complicated, and the guide can be found here.
Want to have certain options only appear in development mode?
const DEBUG = process.env.NODE_ENV !== 'production' // Webpack 1 module.exports = { debug: DEBUG ? true : false, devtool: DEBUG ? 'cheap-module-eval-source-map' : 'hidden-source-map' } // Webpack 2 module.exports = { devtool: DEBUG ? 'cheap-module-source-map' : 'hidden-source-map' }
Webpack 1: Be sure to invoke Webpack as env NODE_ENV=production webpack -p when building your production assets.
Webpack 2: Invoke Webpack as webpack -p when building your production assets. NODE_ENV is automatically set by Webpack.
Want to see what dependencies are the largest? You can use webpack-bundle-size-analyzer.
$ yarn global add webpack-bundle-size-analyzer $ ./node_modules/.bin/webpack --json | webpack-bundle-size-analyzer jquery: 260.93 KB (37.1%) moment: 137.34 KB (19.5%) parsleyjs: 87.88 KB (12.5%) bootstrap-sass: 68.07 KB (9.68%) ...
If you're generating source maps (you should), you can also use source-map-explorer, which also works outside of Webpack.
$ yarn global add source-map-explorer $ source-map-explorer bundle.min.js bundle.min.js.map
Reference: webpack-bundle-size-analyzer, source-map-explorer
React will build dev tools by default. You don't need this in production. Use the EnvironmentPlugin to make these dev tools disappear. This saves you around 30kb.
plugins: [ new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }) ]
Webpack 1: Be sure to invoke Webpack as env NODE_ENV=production webpack -p when building your production assets.
Webpack 2: Invoke Webpack as webpack -p when building your production assets. NODE_ENV is automatically set by Webpack.
Reference: EnvironmentPlugin documentation
Lodash is very useful but usually we only need a small part of its full functionality. lodash-webpack-plugin can help you shrink the lodash build by replacing feature sets of modules with noop, identity, or simpler alternatives.
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin'); const config = { plugins: [ new LodashModuleReplacementPlugin({ path: true, flattening: true }) ] };
This may save you >10kb depending on how much you use lodash.
Ever wanted to do this?
require('./behaviors/*') /* Doesn't work! */
Use require.context.
// http://stackoverflow.com/a/30652110/873870 function requireAll (r) { r.keys().forEach(r) } requireAll(require.context('./behaviors/', true, /\.js$/))
Reference: require.context
If you're seeing this in your debug log when using extract-text-webpack-plugin:
Child extract-text-webpack-plugin:
+ 2 hidden modules
Child extract-text-webpack-plugin:
+ 2 hidden modules
Child extract-text-webpack-plugin:
+ 2 hidden modules
Turn it off using stats: { children: false }.
/* webpack.config.js */ stats: { children: false, },
Reference: extract-text-webpack-plugin#35