Skip to content
This repository has been archived by the owner on Mar 16, 2020. It is now read-only.

Optimizing webpack build with babel & babili #8

Open
boopathi opened this issue Oct 12, 2016 · 10 comments
Open

Optimizing webpack build with babel & babili #8

boopathi opened this issue Oct 12, 2016 · 10 comments

Comments

@boopathi
Copy link
Member

boopathi commented Oct 12, 2016

The current build sequence for a typical webpack project is transpile -> bundle -> minify. As babili doesn't traverse through Objects and its properties (yet), there will not be much optimizations on the bundler generated code (modules[moduleId].call()) other than mangling and whitespace/comments removal. The pipeline can be transformed to (transpile + minify) -> bundle - if the bundler already produces mangled and has an option to output minified (just the syntax and comments) code. But, we could already do this now -

  1. transpile + minify (mangle=false)
  2. bundle - remove dead code module level (tree-shaking?)
  3. mangle + deadcode(if required) + minify(syntax, comments)
// stage 1
{
  loader: 'babel-loader'
  presets: [
    'es2016',
    'react',
    [
      'babili', { // <- options not yet supported (https://github.com/babel/babili/pull/162)
        mangle: false // this will be performed on the entire bundle.
        deadcode: false // not tested which is better for deadcode - stage1 or 3 - just an idea
      }
    ]
  ]
}

// stage 2
bundle - webpack

// stage 3
new BabiliWebpackPlugin({
  mangle: true, // <- option not yet supported
  deadcode: true, // <- option not yet supported
  [everythingelse]: false // <- just a notation
  comments: false,
});
// or 
babel.transform(bundledcode, {
  minified: true, // syntax
  compact: true,
  comments: false,
  plugins: ["mangle", "deadcode"]
})

From babel/website#898 (comment) - edited and added more description

@boopathi
Copy link
Member Author

boopathi commented Nov 26, 2016

babel/minify#162 is merged ..

@nodaguti
Copy link

Just for your information:

With babel/minify#162 shipped, we can now pass options to Babili through the babili property like this:

new BabiliWebpackPlugin({
  babili: {
    presets: [
      [
        require('babel-preset-babili'),
        {
          mangle: { topLevel: true },
          deadcode: false,
          removeConsole: process.env.NODE_ENV === 'production',
        },
      ],
    ],
    plugins: [
      'transform-inline-environment-variables',
    ],
  },
}),

@icd2k3
Copy link

icd2k3 commented Mar 7, 2017

I've tried setting up my webpack plugin config as above, but I still end up with compiled code that is actually larger than just using uglify-webpack-plugin... Any ideas of things I could try? I've tried lots of combinations of config/babelrc but each produces a build larger than that of uglify which doesn't seem right?

Currently this will produce bundles...
Uglify: 325.1kb
Bibili: 339.4kb

.babelrc

{
  "presets": [
    [
      "es2015",
      {
        modules: false
      }
    ],
    "es2017",
    "react",
    "stage-0",
  ],
  "plugins": [
    "transform-object-assign"
  ],
  "env": {
    "production": {
      "presets": ["babili"]
    }
  }
}

webpack.config.js

//...
  devtool: 'cheap-module-source-map',
  module: {
    rules: [
      {
        test    : /\.js$|\.jsx$/,
        exclude : [
          /node_modules/,
          /\.spec\.js$/
        ],
        loaders : [
          'babel-loader',
          'eslint-loader'
        ],
      },
    ],
  },
  plugins: [
    new BabiliPlugin({
      test: /\.js$|\.jsx$/,
      babili: {
        presets: [
          [
            require('babel-preset-babili'),
            {
              mangle: { topLevel: true },
              deadcode: false,
              removeConsole: true,
            },
          ],
        ],
      },
    }),
  ],
//...

@mosesoak
Copy link

mosesoak commented Mar 8, 2017

I'm having the same issue as @icd2k3, the plugin is not doing any basic minification (whitespace removal).

It does seem to be running, since I am using typescript so I need to pass test: /\.tsx?$/, in the 2nd parameter for 'overrides' to get it to run without error.

I'm not trying to do any custom configurations, just get basic minification working. Any idea why it would run without error but fail to minify?

The files are React + es6 + typescript.

@mosesoak
Copy link

mosesoak commented Mar 8, 2017

(I should add that I did not include a .babelrc file in my project since from your docs it seems like I can just used the options/overrides objects in the plugin.)

@seansd-zz
Copy link

Yes for me the minify of variables and what not is happening but agree that white space not getting stripped

@aseem2625
Copy link

aseem2625 commented Jun 13, 2017

@boopathi There is a confusion..
This used to work as of version "babili-webpack-plugin": "0.0.11". It has stopped working now. I don't want to have .babelrc file and trying with this also doesn't help

Below works.

    new BabiliPlugin({
      mangle: { 'topLevel': true },
      deadcode: true
    }),

But it doesn't conform to the README.md

What's the correct way of using it as per latest version? Can you please help!

@qm3ster
Copy link

qm3ster commented Sep 23, 2017

Is there really a reason to use this strategy?
So far, I have seen that basically every rule I leave enabled improved bundle size, even without node_modules dependencies.
When would you need to optimize for compile time rather than bundle size?

@oyeanuj
Copy link

oyeanuj commented Nov 3, 2017

@boopathi Coming here from the README, and reading through the comments in this thread, I am still unclear on what strategy is recommended? Since the plugin has seen changes in the year since the thread started, could you suggest your current recommendations? Thank you!

@manigandham
Copy link

manigandham commented Dec 20, 2017

The defaults are work fine and the why section of the readme explains the benefits of doing the minification at the end (works on the entire output and uses ES6 parsing). Below is an example of what we run to generate an optimized bundle while including all the polyfills for the minimum browsers you want to support:

webpack.config.js

const path = require('path');
const webpack = require('webpack');
const BabelMinifyPlugin = require('babel-minify-webpack-plugin');

module.exports = (env) => {
    return [
        {
            context: __dirname,
            entry: { app: [path.join(__dirname, 'index.js')] },
            module: {
                rules: [
                    { test: /\.js$/, exclude: /node_modules/, loader: ['babel-loader'] },
                ]
            },
            output: {
                path: path.join(__dirname, './dist'),
                filename: '[name].js'
            },
            plugins: [
                new webpack.optimize.ModuleConcatenationPlugin(),
                new BabelMinifyPlugin()
            ]
        }
    ];
};

.babelrc

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": [ "safari 10", "ie 11", "ios 9" ]
        },
        "modules": false,
        "useBuiltIns": true
      }
    ]
  ],
  "plugins": [
    "transform-runtime"
  ],
  "comments": false
}

Include the statement import 'babel-polyfill'; in your code (only once, like in your entry script file) and Babel will take care of the rest by adding the appropriate polyfills for all the browser requirements you have, and then bundling and minifying the entire output as a whole.

Note that this will include polyfills you might not be using because those are added to the global scope and won't be removed as part of the dead code elimination. If that's a big deal, then remove the import statement described above and add in the polyfills manually. You can use the debug output for babel minify to get a list of polyfills that might be needed for your browser requirements.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants