I wanted to minify all my js & CSS using webpack for my production deployment & when I start work in development mode it should get prettify, I am new to webpack & not sure how I make this work, below is my webpack config, how I can modify it to work separately for development & production environment?
var webpack = require('webpack');
var path = require('path');
// Webpack Config
var webpackConfig = {
entry: {
'polyfills': './src/polyfills.browser.ts',
'vendor': './src/vendor.browser.ts',
'main': './src/main.browser.ts',
},
output: {
path: './dist',
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.optimize.CommonsChunkPlugin({ name: ['main', 'vendor', 'polyfills'], minChunks: Infinity }),
],
module: {
loaders: [
// .ts files for TypeScript
{ test: /\.ts$/, loaders: ['awesome-typescript-loader', 'angular2-template-loader'] },
{ test: /\.css$/, loaders: ['to-string-loader', 'css-loader'] },
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.json$/, loader: 'json-loader' },
]
}
};
// Our Webpack Defaults
var defaultConfig = {
devtool: 'cheap-module-source-map',
cache: true,
debug: true,
output: {
filename: '[name].bundle.js',
sourceMapFilename: '[name].map',
chunkFilename: '[id].chunk.js'
},
module: {
preLoaders: [
{
test: /\.js$/,
loader: 'source-map-loader',
exclude: [
// these packages have problems with their sourcemaps
path.join(__dirname, 'node_modules', 'rxjs'),
path.join(__dirname, 'node_modules', '@angular2-material'),
path.join(__dirname, 'node_modules', '@angular'),
]
}
],
noParse: [
path.join(__dirname, 'node_modules', 'zone.js', 'dist'),
path.join(__dirname, 'node_modules', 'angular2', 'bundles')
]
},
resolve: {
root: [ path.join(__dirname, 'src') ],
extensions: ['', '.ts', '.js', '.json']
},
devServer: {
historyApiFallback: true,
watchOptions: { aggregateTimeout: 300, poll: 1000 }
},
node: {
global: 1,
crypto: 'empty',
module: 0,
Buffer: 0,
clearImmediate: 0,
setImmediate: 0
},
}
var webpackMerge = require('webpack-merge');
module.exports = webpackMerge(defaultConfig, webpackConfig);
So when I enable anggular 2 enableProduction
webpack should also call production code and minify JS & CSS
You can create a webpack.config.production.js, then in the main webpack.config.js you can import the production config like this:
var environment = process.env.NODE_ENV ? process.env.NODE_ENV : "local";
var envSpecificConfig = require('./webpack.config.' + environment);
where environment is set as an environment variable by gulp or your build server or by other means.
So in principle all the common config would go into the webpack.config.js and production stuff would go in webpack.config.production.js.
Example configs here (webpack.config.js first):
var path = require('path');
var webpack = require('webpack');
var merge = require('extendify')({ isDeep: true, arrays: 'concat' });
var environment = process.env.NODE_ENV ? process.env.NODE_ENV : "local";
var envSpecificConfig = require('./webpack.config.' + environment);
module.exports = merge({
...all your standard stuff you already have here
}, envSpecificConfig);
Then in the webpack.config.production.js
var webpack = require('webpack');
var path = require( 'path' );
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
minimize: true,
mangle: false // Due to https://github.com/angular/angular/issues/6678
})
]
};
This way you can have any number of environment specific configs and you just set the environment variable to match the config file name.
Set different Environment mode with webpack and webpack.DefinePlugin
Best practice to have different files for each environment so it's easy to maintain and have different configuration depends on environment. I have created a angular2 webpack seed and there in config folder you can find webpack files.
- webpack.common.js
- webpack.dev.js
- webpack.prod.js
DefinePlugin
The DefinePlugin allows you to create global constants which can be configured at compile time. This can be very useful for allowing different behaviour between development builds and release builds. For example, you might use a global constant to determine whether logging takes place; perhaps you perform logging in your development build but not in the release build. That’s the sort of scenario the DefinePlugin facilates.
Example
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object")
})
Each key passed into DefinePlugin is an identifier or multiple identifiers joined with ..
- If the value is a string it will be used as a code fragment.
- If the value isn’t a string, it will be stringified (including functions).
- If the value is an object all keys are defined the same way.
- If you prefix typeof to the key, it’s only defined for typeof calls.
The values will be inlined into the code which allows a minification pass to remove the redundant conditional.
Example
if (!PRODUCTION)
console.log('Debug info')
if (PRODUCTION)
console.log('Production log')
Source
Webpack Seed
For now here is how I am minifying it for production, its a manual work but atleast, for now, its doing the job. In config added minimize
argument which you will put while running the watcher i.e. webpack --watch --minimize
, below is the code:
...
var path = require('path');
var minimize = process.argv.indexOf('--minimize') !== -1;
...
...
...
if (minimize) {
webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin());
}
var webpackMerge = require('webpack-merge');
module.exports = webpackMerge(defaultConfig, webpackConfig);