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:
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
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?
Here's a demo repo that can reproduce the situation
https://github.com/Milanzor/babel-and-treeshaking-question
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.
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.
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.
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.