24

I got my webpack generating a large main.js file (1.7mb) with a small project of ~20-30 files less than 100 lines each. The dependencies required are few in number (React, Fluxible) and I am using every optimize plugin I can understand:

module.exports = {
  output: {
    path: './build',
    publicPath: '/public/',
    filename: '[name].js'
  },
  debug: false,
  devtool: 'eval',
  target: 'web',
  entry: [
  'bootstrap-sass!./bootstrap-sass.config.js',
  './client.js',
  ],
  stats: {
    colors: true,
    reasons: false
  },
  resolve: {
    extensions: ['', '.js'],
    alias: {
      'styles': __dirname + '/src/styles',
      'components': __dirname + '/src/scripts/components',
      'actions': __dirname + '/src/scripts/actions',
      'stores': __dirname + '/src/scripts/stores',
      'constants': __dirname + '/src/scripts/constants',
      'mixins': __dirname + '/src/scripts/mixins',
      'configs': __dirname + '/src/scripts/configs',
      'utils': __dirname + '/src/scripts/utils'
    }
  },
  module: {
    loaders: [
      { test: /\.css$/, loader: 'style!css' },
      { test: /\.js$/, exclude: /node_modules/, loader: require.resolve('babel-loader') },
      { test: /\.json$/, loader: 'json-loader'},
      { test: /\.(png|svg|jpg)$/, loader: 'url-loader?limit=8192' },
      { test: /\.(ttf|eot|svg|woff|woff(2))(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?name=/[name].[ext]"},
      { test: /\.scss$/,
        loader: ExtractTextPlugin.extract('style-loader',
          'css!sass?outputStyle=expanded&' +
          "includePaths[]=" +
          (path.resolve(__dirname, "./node_modules"))
          )
      }
    ]
  },
  plugins: [
    new webpack.NoErrorsPlugin(),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "windows.jQuery": "jquery"
    }),
    new ExtractTextPlugin("[name].css", {allChunks: true}),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.AggressiveMergingPlugin()
  ],

};

What am I doing wrong or where can I further improve the size of the file?

Mohamed El Mahallawy
  • 13,024
  • 13
  • 52
  • 84

3 Answers3

15

I got my react down from 2.1mb down to 160kb gzipped just by doing the things here (devtools: 'source-map'), using uglifyjs with the default settings (without gzip it ends up being about 670kb).

It's probably not that great, but at least it's not crazy anymore.

For posterity, here is my webpack config:

// webpack.config.js
var webpack = require('webpack');

module.exports = {
    devtool: 'source-map',
    entry: [
        'webpack-dev-server/client?http://127.0.0.1:2992',
        'webpack/hot/only-dev-server',
        './js/main'
    ],
    output: {
        path: './out/',
        filename: 'main.js',
        chunkFilename: '[name]-[chunkhash].js',
        publicPath: 'http://127.0.0.1:2992/out/'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /(node_modules|bower_components)/,
                loaders: ['react-hot', 'babel?optional=runtime&stage=0&plugins=typecheck']
            }
        ]
    },
    progress: true,
    resolve: {
        modulesDirectories: [
            'js',
            'node_modules'
        ],
        extensions: ['', '.json', '.js']
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
        new webpack.DefinePlugin({
            'process.env': {
                // This has effect on the react lib size
                'NODE_ENV': JSON.stringify('production'),
            }
        }),
        new webpack.optimize.UglifyJsPlugin()
    ]
};
pip
  • 453
  • 2
  • 13
  • 1
    My project results in a similar filesize as yours, and likewise it's not crazy, but then again my website has barely anything on it so I'm expecting the filesize to still be much smaller. I'm linking it; check e.g. package.json in it to see if there is anything your project also uses that might take up a lot of space: https://github.com/amcsi/szeremi/tree/f93671a – Attila Szeremi Feb 28 '16 at 01:00
  • I tookout the HotModuleReplacementPlugin for my prod release – P.Brian.Mackey Aug 25 '16 at 02:15
10

You should set at least

plugins: [
  new webpack.DefinePlugin({
    'process.env': {
      // This has effect on the react lib size
      'NODE_ENV': JSON.stringify('production'),
    }
  }),
  ...
],

That will help considerably with React.

In addition setting devtool to source-map is preferable in production environment. See official documentation for more information.

You could try to inspect output using the analyse tool. To get the JSON it expects you'll need to do something like webpack --json > stats.json and then pass that stats.json to the tool. That might give you some insight.

Juho Vepsäläinen
  • 26,573
  • 12
  • 79
  • 105
  • Yes definitely I will take a look at this and see how it effects the code. Also, I found my mistake which I'd suggest adding to the answer, I was doing `devtools: true` which caused my file to be huge while for production it doesn't need to be true. – Mohamed El Mahallawy Jun 25 '15 at 17:59
  • 1
    Cool, I added that. Forgot about `devtool` entirely. – Juho Vepsäläinen Jun 26 '15 at 06:58
  • An alternative, command line tool for webpack bundle analysis: https://github.com/robertknight/webpack-bundle-size-analyzer – jmu Jan 21 '16 at 16:54
8

You can also take a look at Webpack Bundle Analyzer.

It represents bundle content as convenient interactive zoomable treemap.

th0r
  • 515
  • 4
  • 9