Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack 3, Babel and Tree shaking not working

I'm trying to find a way to tree-shake my modules and use Babel with Webpack.

If I take the example code from the webpack documentation (https://webpack.js.org/guides/tree-shaking/) and run it, the modules/functions/other exports that are not used are marked as unused harmony exports, which is the expected outcome. After running webpack with the -p argument (production), webpack uses UglifyJS to remove the dead and unused code (to tree-shake).

Now, if I add babel-loader to my webpack config file, my ES2015 modules are transpiled but now are not marked as unused exports anymore.

So for example:

math.js

export function square(x) {
  return x * x;
}

export function cube(x) {
  return x * x * x;
}

app.js (my entry file)

import {square} from './math.js'

Running this through webpack WITHOUT babel-loader, the cube function will get marked as unused and removed after compiling for production (-p).

Running this through webpack WITH babel-loader, the cube function will not be marked as unused and will stay in the compiled bundle.

What am I missing?

Edit

Here's a demo repo that can reproduce the situation

https://github.com/Milanzor/babel-and-treeshaking-question

Update

If I add a .babelrc:

{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "entry",
      "debug": true,
      "targets": {
        "browsers": ["last 2 versions"]
      }
    }]
  ]
}

I get the same result, but if I add modules: false to the preset-env options, Babel doesn't compile the modules to ES5 and Webpack marks the modules as unused again.

Conclusion

I need to find a way to tell Webpack that my modules are transpiled with Babel, or I need to find a way to tell Babel to scan for unused codes itself.

like image 603
Milanzor Avatar asked Dec 05 '17 22:12

Milanzor


People also ask

Why is webpack not tree shaking?

In webpack, tree shaking works with both ECMAScript modules (ESM) and CommonJS, but it does not work with Asynchronous Module Definition (AMD) or Universal Module Definition (UMD).

Does webpack do tree shaking by default?

Basic Webpack ConfigurationWebpack only does tree shaking when doing minification, which will only occur in production model. Second, you must set the optimization option “usedExports” to true. This means that Webpack will identify any code it thinks isn't being used and mark it during the initial bundling step.

Does webpack tree shake CSS?

By default Webpack side effects property is set to false; which doesn't enable the tree shaking technique. By flipping the switch and turning the value into true, it will enable the tree shaking technique, and reduce your CSS file size by removing unused code. Smaller CSS files means better performance.


1 Answers

Webpack's built-in tree shaking works on ES6 module syntax only. If you're using Babel's defaults settings, Babel will compile ES6 modules to CommonJS modules, leaving nothing for Webpack to work with.

Generally people using Webpack will want to pass modules: false to the preset that they are using for ES6 (probably preset-env?), thus doing

{
  presets: [
    ['env', { modules: false }],
  ],
}

alternatively you could consider using a plugin like https://github.com/indutny/webpack-common-shake to enable tree-shaking for CommonJS modules.

Update

If you're using Babel 7 (and thus @babel/preset-env), the modules option is now automatically false when used in Webpack, so this explicit configuration should no longer be needed.

like image 87
loganfsmyth Avatar answered Sep 28 '22 22:09

loganfsmyth