I find my webpack vendor bundles very large (~1.6 MB originally). After using webpack-bundle-size-analyzer, I found angular to be contributing a large part to this.
➜ dapper-ui git:(master) webpack --config ./conf/webpack-dist.conf.js --json | webpack-bundle-size-analyzer
angular: 1.13 MB (25.9%)
lodash: 526.94 KB (11.8%)
moment: 429.12 KB (9.58%)
angular-ui-router: 339.35 KB (7.58%)
chart.js: 311.27 KB (6.95%)
angular-ui-bootstrap: 264.26 KB (5.90%)
ng-table: 197.55 KB (4.41%)
angular-animate: 147.1 KB (3.29%)
angularjs-slider: 87.52 KB (1.95%)
validator: 70.85 KB (1.58%)
bootstrap-sass: 68.07 KB (1.52%)
buffer: 47.47 KB (1.06%)
angular-resource: 34.45 KB (0.769%)
angular-messages: 27.39 KB (0.612%)
angular-file-upload: 20.36 KB (0.455%)
angular-sticky-plugin: 19.06 KB (0.426%)
color-convert: 16.53 KB (0.369%)
ng-tags-input: 15.62 KB (0.349%)
angular-aria: 14.87 KB (0.332%)
angular-ui-bootstrap-datetimepicker: 13.26 KB (0.296%)
angular-chart.js: 12.7 KB (0.284%)
chartjs-color: 10.96 KB (0.245%)
chartjs-color-string: 5.9 KB (0.132%)
color-name: 4.49 KB (0.100%)
base64-js: 3.4 KB (0.0760%)
angular-validation-match: 2.06 KB (0.0460%)
ieee754: 2.01 KB (0.0448%)
css-loader: 1.47 KB (0.0328%)
webpack: 1.03 KB (0.0230%)
isarray: 132 B (0.00288%)
<self>: 622.84 KB (13.9%)
I tried checked the minified angular file is ~160kb. I guess its not using or showing the minified size. In any case, I am using Uglify so I'd expect the size to be similar?
I tried using webpack aliases, to make webpack use the minified bundles but that didnt reduce the vendor bundle much.
For the time being I split up the vendor bundles into 4 parts so they can be downloaded in parallel to speed things up but am still curious how to do better and also why is angular and other libraries so large even tho the minified code provided is significantly smaller.
My webpack config:
const webpack = require('webpack');
const conf = require('./gulp.conf');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const pkg = require('../package.json');
const autoprefixer = require('autoprefixer');
const deps = Object.keys(pkg.dependencies);
const vendorNumInBundle = Math.ceil(deps.length / 4)
module.exports = {
module: {
preLoaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint'
}
],
loaders: [
{
test: /.json$/,
loaders: [
'json'
]
},
{
test: /\.(css|less)$/,
loaders: ExtractTextPlugin.extract(['css-loader', 'postcss-loader', 'less-loader'])
},
{
test: /\.scss$/,
loaders: ExtractTextPlugin.extract(['css-loader', 'postcss-loader', 'sass-loader'])
},
{
test: /\.js$/,
exclude: /node_modules/,
loaders: [
'ng-annotate'
]
},
{
test: /.html$/,
loaders: [
'html'
]
}
]
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: conf.path.src('index.html')
}),
new webpack.optimize.UglifyJsPlugin({
compress: {unused: true, dead_code: true, warnings: false}, // eslint-disable-line camelcase
comments: false
}),
new ExtractTextPlugin('index-[contenthash].css'),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor5', 'vendor4', 'vendor3', 'vendor2', 'vendor1'],
minChunks: Infinity
}),
function()
{
this.plugin("done", function(stats)
{
if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') == -1)
{
console.log(stats.compilation.errors);
process.exit(1); // or throw new Error('webpack build failed.');
}
// ...
});
}
],
postcss: () => [autoprefixer],
output: {
path: path.join(process.cwd(), conf.paths.dist),
filename: '[name]-[hash].js'
},
entry: {
app: `./${conf.path.src('index')}`,
vendor1: deps.slice(0, vendorNumInBundle),
vendor2: deps.slice(vendorNumInBundle, vendorNumInBundle * 2),
vendor3: deps.slice(vendorNumInBundle * 2, vendorNumInBundle * 3),
vendor4: deps.slice(vendorNumInBundle * 3),
vendor5: [
'./src/assets/js/angular-natural-language.min.js',
'./src/assets/js/angular-img-cropper.js',
'./src/assets/js/satellizer.min.js',
'./src/assets/js/satellizer.min.js',
'./src/assets/js/angular-bootstrap-toggle',
]
}
};