Webpack 3,Babel 和 Tree shaking 不起作用

Webpack 3, Babel and Tree shaking not working

我正在尝试找到一种方法来摇树我的模块并将 Babel 与 Webpack 一起使用。

如果我从 webpack 文档 (https://webpack.js.org/guides/tree-shaking/) 和 运行 中获取示例代码,未使用的 modules/functions/other 导出被标记为未使用的和谐导出,即预期的结果。 运行使用 -p 参数(生产)使用 webpack 后,webpack 使用 UglifyJS 删除死的和未使用的代码(摇树)。

现在,如果我将 babel-loader 添加到我的 webpack 配置文件中,我的 ES2015 模块会被转译,但现在不再被标记为未使用的导出。

例如:

math.js

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

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

app.js(我的参赛档案)

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

运行 通过 webpack WITHOUT babel-loader,cube 函数将被标记为未使用并在编译生产后删除 (-p) .

运行 通过 webpack WITH babel-loader,cube 函数不会被标记为未使用,将保留在已编译的包中。

我错过了什么?

编辑

这是一个可以重现这种情况的演示回购协议

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

更新

如果我添加一个.babelrc:

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

我得到了相同的结果,但是如果我将 modules: false 添加到 preset-env 选项,Babel 不会将模块编译为 ES5 并且 Webpack 再次将模块标记为未使用。

结论

我需要找到一种方法告诉 Webpack 我的模块是用 Babel 转译的,或者我需要找到一种方法告诉 Babel 自己扫描未使用的代码。

Webpack 的内置 tree shaking 仅适用于 ES6 模块语法。如果你使用 Babel 的默认设置,Babel 会将 ES6 模块编译为 CommonJS 模块,不留任何东西给 Webpack 使用。

通常使用 Webpack 的人会希望将 modules: false 传递给他们用于 ES6 的预设(可能 preset-env?),因此

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

或者你可以考虑使用像 https://github.com/indutny/webpack-common-shake 这样的插件来为 CommonJS 模块启用 tree-shaking。

更新

如果您使用的是 Babel 7(因此 @babel/preset-env),modules 选项现在在 Webpack 中使用时会自动 false,因此不应再使用此显式配置需要。