This page explains how to generate production builds with webpack.
Running webpack -p
(or equivalently webpack --optimize-minimize --define process.env.NODE_ENV="'production'"
). This performs the following steps:
UglifyJsPlugin
LoaderOptionsPlugin
, see its documentation
webpack comes with UglifyJsPlugin
, which runs UglifyJS in order to minimize the output. The plugin supports all of UglifyJS options. Specifying --optimize-minimize
on the command line, the following plugin configuration is added:
// webpack.config.js const webpack = require('webpack'); module.exports = { /*...*/ plugins:[ new webpack.optimize.UglifyJsPlugin({ sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0) }) ] };
Thus, depending on the devtool options, Source Maps are generated.
We encourage you to have Source Maps enabled in production. They are useful for debugging and to run benchmark tests. webpack can generate inline Source Maps included in the bundles or separated files.
In your configuration, use the devtool
object to set the Source Map type. We currently support seven types of Source Maps. You can find more information about them in our configuration documentation page.
One of the good options to go is using cheap-module-source-map
which simplifies the Source Maps to a single mapping per line.
Running webpack -p
(or --define process.env.NODE_ENV="'production'"
) invokes the DefinePlugin
in the following way:
// webpack.config.js const webpack = require('webpack'); module.exports = { /*...*/ plugins:[ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }) ] };
The DefinePlugin
performs search-and-replace operations on the original source code. Any occurrence of process.env.NODE_ENV
in the imported code is replaced by "production"
. Thus, checks like if (process.env.NODE_ENV !== 'production') console.log('...')
are evaluated to if (false) console.log('...')
and finally minified away using UglifyJS
.
Technically,NODE_ENV
is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine development-vs-production behavior, by both server tools, build scripts, and client-side libraries. Contrary to expectations,process.env.NODE_ENV
is not set to"production"
within the build scriptwebpack.config.js
, see #2537. Thus, conditionals likeprocess.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'
do not work as expected. See how to use environment variables.
When we do have multiple configurations in mind for different environments, the easiest way is to write separate js files for each environment. For example:
dev.js
module.exports = function (env) { return { devtool: 'cheap-module-source-map', output: { path: path.join(__dirname, '/../dist/assets'), filename: '[name].bundle.js', publicPath: publicPath, sourceMapFilename: '[name].map' }, devServer: { port: 7777, host: 'localhost', historyApiFallback: true, noInfo: false, stats: 'minimal', publicPath: publicPath } } }
prod.js
module.exports = function (env) { return { output: { path: path.join(__dirname, '/../dist/assets'), filename: '[name].bundle.js', publicPath: publicPath, sourceMapFilename: '[name].map' }, plugins: [ new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }), new webpack.optimize.UglifyJsPlugin({ beautify: false, mangle: { screw_ie8: true, keep_fnames: true }, compress: { screw_ie8: true }, comments: false }) ] } }
Have the following snippet in your webpack.config.js:
function buildConfig(env) { return require('./config/' + env + '.js')(env) } module.exports = buildConfig;
And from our package.json, where we build our application using webpack, the command goes like this:
"build:dev": "webpack --env=dev --progress --profile --colors", "build:dist": "webpack --env=prod --progress --profile --colors",
You can see that we passed the environment variable to our webpack.config.js file. The environment variable is then passed to buildConfig
method which simply loads the right js file for the build.
An advanced approach would be to have a base configuration file, put in all common functionalities, and then have environment specific files and simply use 'webpack-merge' to merge them. This would help to avoid code repetitions. For example, you could have all your base configurations like resolving your js, ts, png, jpeg, json and so on.. in a common base file as follows:
base.js
module.exports = function() { return { entry: { 'polyfills': './src/polyfills.ts', 'vendor': './src/vendor.ts', 'main': './src/main.ts' }, output: { path: path.join(__dirname, '/../dist/assets'), filename: '[name].bundle.js', publicPath: publicPath, sourceMapFilename: '[name].map' }, resolve: { extensions: ['.ts', '.js', '.json'], modules: [path.join(__dirname, 'src'), 'node_modules'] }, module: { rules: [{ test: /\.ts$/, use: [ 'awesome-typescript-loader', 'angular2-template-loader' ], exclude: [/\.(spec|e2e)\.ts$/] }, { test: /\.css$/, use: ['to-string-loader', 'css-loader'] }, { test: /\.(jpg|png|gif)$/, use: 'file-loader' }, { test: /\.(woff|woff2|eot|ttf|svg)$/, use: { loader: 'url-loader', options: { limit: 100000 } } }], }, plugins: [ new ForkCheckerPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: ['polyfills', 'vendor'].reverse() }), new HtmlWebpackPlugin({ template: 'src/index.html', chunksSortMode: 'dependency' }) ], }; }
And then merge this base config with an environment specific configuration file using 'webpack-merge'. Let us look at an example where we merge our prod file, mentioned above, with this base config file using 'webpack-merge':
prod.js (updated)
const webpackMerge = require('webpack-merge'); const commonConfig = require('./base.js'); module.exports = function(env) { return webpackMerge(commonConfig(), { plugins: [ new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }), new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': JSON.stringify('production') } }), new webpack.optimize.UglifyJsPlugin({ beautify: false, mangle: { screw_ie8: true, keep_fnames: true }, compress: { screw_ie8: true }, comments: false }) ] }) }
You will notice three major updates to our 'prod.js' file.
The choice of what is going to be common across all your environments is up to you, however. We have just demonstrated a few that could typically be common across environments when we build our application.
© 2012–2016 Tobias Koppers
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/guides/production-build/