1

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()
  ])
  )
});
Greg Venech
  • 8,062
  • 2
  • 19
  • 29
ilse2005
  • 11,189
  • 5
  • 51
  • 75
  • How big do you think it should be? – Evan Davis Mar 15 '16 at 20:35
  • Honestly, I don't know. Is this a "normal" size? – ilse2005 Mar 15 '16 at 20:37
  • 1
    A "normal" size for what kind of app? Is your bundle really minified? Looks like you are only reading the "verbose" argument and not handing the --release flag to the webpack call. – Andreas Jägle Mar 15 '16 at 20:45
  • Yes it is minified. The `--release` flag gets evaluated in the webpack.config. I added this to my question. – ilse2005 Mar 15 '16 at 20:53
  • I'm not sure how to answer "what kind of application". The app is based on react and react-redux. I'm talking about this page http://www.wg-cast.de/ – ilse2005 Mar 15 '16 at 21:02
  • What loaders are you using? Are you extracting CSS or using the style loader to package them with the JS and have it inserted in a style tag? Assets like images can be inlined with certain loaders which can greatly increase build size (especially if you aren't [code splitting](http://webpack.github.io/docs/code-splitting.html)). As @ajaegle mentioned it's also hard to approximate your build size without knowing dependencies and project size... – Greg Venech Mar 16 '16 at 08:31
  • 1
    Another consideration might be ensuring `NODE_ENV=production` is set correctly. In some libraries such as React this will allow the minifier to strip out a lot of unused code from the production build. – djskinner Mar 16 '16 at 09:08

1 Answers1

2

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.

Community
  • 1
  • 1
Greg Venech
  • 8,062
  • 2
  • 19
  • 29