Search code examples
javascripthandlebars.jswebpackmomentjs

Why is my Webpack bundle so large?


I am writing some JavaScript which uses Moment.js and Handlebars. Moment.js is supposed to be 30 KB gzipped and Handlebars is supposed to be less than 10 KB gzipped. But when I use Webpack to bundle my code, I get a resulting file which is 271 KB!

I installed webpack-bundle-size-analyzer to investigate and found much larger files than expected:

$ webpack --json | webpack-bundle-size-analyzer
moment: 454.54 KB (74.1%)
handlebars: 94.39 KB (15.4%)
twitter-text: 62.3 KB (10.2%)
<self>: 1.94 KB (0.317%)

I have a feeling I am doing something which is causing a lot of unnecessary things to be loaded since I was expecting a final file size <100 KB.

main.js

var template = require('./template.handlebars')
var Handlebars = require('handlebars/runtime')
var twitter = require('twitter-text')
var moment = require('moment')

webpack.config.js

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',

  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'bundle.min.js'
  },

  resolveLoader: {
    root: path.join(__dirname, 'node_modules')
  },

  module: {
    loaders: [
      {
        test: /\.handlebars$/,
        loader: 'handlebars-loader'
      }
    ]
  },

  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
}

Solution

  • Update on Aug 10

    You may refer to this issue on github/moment. Basically you can eliminate out all other locales which you don't need.

    Extract from the comments:

    plugins: [
        new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|zh-tw)$/)
    ]
    

    I think the webpack did its best already. When you look into the files in node_modules/moment/min/

    You will see these:

    220K  moment-with-locales.min.js
     57K  moment.min.js
    

    So, if you include the moment with locales, 2XXKB is making sense. To further reduce the size, you may try

    1. include the moment without locales explicitly

      var moment = require('moment/min/moment.min')
      // if you dun need the locale support
      
    2. Or you can try to compress your output with gz manually with this plugin compression-webpack-plugin.