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
vendor
entry 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