Why is output bundle built with Webpack and Gulp so big (>1.9Mb)?

I am using webpack and gulp via node/npm to build and uglify browser application. The problem is that the output app.js is about 1.9Mb. It seems far too big and suggests I'm probably missing something.

I start the build process using gulp build --release

This is my gulp file:

import path from 'path';
import cp from 'child_process';
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import del from 'del';
import mkdirp from 'mkdirp';
import runSequence from 'run-sequence';
import webpack from 'webpack';
import minimist from 'minimist';

const $ = gulpLoadPlugins();
const argv = minimist(process.argv.slice(2));
const src = Object.create(null);

let watch = false;
let browserSync;

// The default task
gulp.task('default', ['sync']);

// Clean output directory
gulp.task('clean', cb => {
  del(['.tmp', 'build/*', '!build/.git'], {dot: true}, () => {
    mkdirp('build/public', cb);
  });
});

// Static files
gulp.task('assets', () => {
  src.assets = 'src/public/**';
  return gulp.src(src.assets)
    .pipe($.changed('build/public'))
    .pipe(gulp.dest('build/public'))
    .pipe($.size({title: 'assets'}));
});

// Resource files
gulp.task('resources', () => {
  src.resources = [
    'package.json',
    'src/content*/**',
    'src/templates*/**'
  ];
  return gulp.src(src.resources)
    .pipe($.changed('build'))
    .pipe(gulp.dest('build'))
    .pipe($.size({title: 'resources'}));
});


// Bundle
gulp.task('bundle', cb => {
  const config = require('./webpack.config.js');
  const bundler = webpack(config);
  const verbose = !!argv.verbose;
  let bundlerRunCount = 0;

  function bundle(err, stats) {
    if (err) {
      throw new $.util.PluginError('webpack', err);
    }

    if (++bundlerRunCount === (watch ? config.length : 1)) {
      return cb();
    }
  }

  if (watch) {
    bundler.watch(200, bundle);
  } else {
    bundler.run(bundle);
  }
});

// Build the app from source code
gulp.task('build', ['clean'], cb => {
  runSequence(['assets', 'resources'], ['bundle'], cb);
});
EDIT:

The final app.js is minified and I am using DedupePlugin, UglifyJsPlugin, and AggressiveMergingPlugin as well. Here is the the relevant (I hope) part of my webpack.config

const DEBUG = !argv.release;

const appConfig = merge({}, config, {
  entry: './src/app.js',
  output: {
    path: './build/public',
    filename: 'app.js'
  },
  node: {
    fs: 'empty'
  },
  devtool: DEBUG ? 'eval-cheap-module-source-map' : false,
  plugins: config.plugins.concat([
    new DefinePlugin(merge(GLOBALS, {
      '__SERVER__': false
    }))
  ].concat(DEBUG ? [] : [
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.optimize.AggressiveMergingPlugin()
  ])
  )
});

Answers


I'm not very familiar with Gulp but I know seeing my initial Webpack build sizes, especially the dev-server outputs, coming from Grunt were pretty intimidating...

Solutions
  1. Check your loaders, see what assets/data/code are being inlined with your javascript
  2. Double check the packages you are importing. Maybe some packages you've installed are larger than you expected. (React by itself is ~150mb minified)
  3. See what modules are showing up in your build. If you run the dev-server you should see a whole list. Maybe some are being duplicated or things are included that you didn't intend to add, such as dev packages.
  4. See the code splitting docs and try creating some child bundles (I like the promise-loader personally) but make sure you also use the CommonsChunkPlugin to deduplicate shared dependencies.
  5. Check out tree shaking with Webpack v2
Ideas

Webpack is amazing but takes a bit more getting used than many other front-end build tools. I would highly recommend trying Webpack by itself on some smaller projects to start instead of mixed in with other tools. I'd be surprised if there was something you were doing with Gulp that you couldn't do with Webpack and you'd save yourself the headache of making two build tools work together.

Hope this helps... I would also check out Pete Hunt's Webpack HowTo and Christian Alfoni's React-Webpack Cookbook if you are using React.

Similar Questions
Update

Definitely look into the NODE_ENV=production as @djskinner mentioned above to make sure the npm react package is aware that you're doing a production build.


Need Your Help

How do version numbers work for MRI Ruby?

ruby versioning

A recent question, "What happened with Ruby 1.9.2?", made me wonder about version numbers for MRI Ruby mean.

Ignore ng-click when opening dropdown

html angularjs html-select angularjs-ng-click angularjs-ng-change

I have a list with options, which I loop into a select with ng-options. Then I would like to call a function, when I click on one of the options. I tried it first with ng-change, but the problem I ...