Webpack 3 + React — Production build tips

David Lazic
Jul 6, 2017 · 6 min read

Migrate Webpack version

plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]

Code splitting & cashing

entry: {
app: path.resolve(sourcePath, 'index.js')
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js',
publicPath: '/'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[chunkhash].js',
minChunks (module) {
return module.context &&
module.context.indexOf('node_modules') >= 0;
}
})
]

Dynamic import & lazy-loading?


Minification

const HtmlWebpackPlugin = require('html-webpack-plugin');plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.ejs'),
path: buildPath,
excludeChunks: ['base'],
filename: 'index.html',
minify: {
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
removeComments: true,
removeRedundantAttributes: true
}
})
]
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true
},
output: {
comments: false
}
}),
new webpack.HashedModuleIdsPlugin()
]
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]

Internalize critical CSS

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin');
plugins: [
new ExtractTextPlugin({
filename: '[name].[contenthash].css',
allChunks: true
}),
new StyleExtHtmlWebpackPlugin({
minify: true
})
]

Source maps

devtool: 'source-map'

Async and defer

const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');plugins: [
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'defer'
})
]

Dns-prefetch and preload

<link rel="dns-prefetch" href="https://www.<example_domain>.com">
const PreloadWebpackPlugin = require('preload-webpack-plugin');plugins: [
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script',
include: 'all',
fileBlacklist: [/\.(css|map)$/, /base?.+/]
})
]

Enable gzip compression

const CompressionPlugin = require('compression-webpack-plugin');plugins: [
new CompressionPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8
})
]

Service worker



Results

app.83852f151d1eccbe4a08.js         2.63 MB
app.83852f151d1eccbe4a08.js.map 3.08 MB
index.html 1.31 kB
Environment: DEVELOPMENT
app.6c682e3a87517dd36425.js.gz                  21.9 kB
app.a5a5d15f6b07d45545a0794a327ab904.css.gz 30.9 kB
vendor.68f62e37ce5bcaf5df30.js.gz 220 kB
index.html 13.7 kB
Environment: PRODUCTION

Conclusion

Netscape

A community dedicated to those who use JavaScript every day.

David Lazic

Written by

Senior Developer @ Deploy Inc.

Netscape

Netscape

A community dedicated to those who use JavaScript every day.