12

我正在尝试找到一种方法来对我的模块进行 tree-shaking 并将 Babel 与 Webpack 一起使用。

如果我从 webpack 文档 ( https://webpack.js.org/guides/tree-shaking/ ) 中获取示例代码并运行它,未使用的模块/函数/其他导出被标记为未使用的和谐导出,这是预期的结果。在使用 -p 参数(生产)运行 webpack 之后,webpack 使用 UglifyJS 删除死的和未使用的代码(用于 tree-shake)。

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

例如:

数学.js

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

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

app.js(我的入口文件)

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

在没有babel-loader 的情况下通过 webpack 运行它,该cube函数将被标记为未使用并在编译生产后删除(-p)。

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

我错过了什么?

编辑

这是一个可以重现这种情况的演示 repo

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 自己扫描未使用的代码。

4

1 回答 1

32

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选项现在false在 Webpack 中使用时会自动使用,因此不再需要此显式配置。

于 2017-12-06T13:28:48.067 回答