【问题标题】:Webpack 3, Babel and Tree shaking not workingWebpack 3,Babel 和 Tree Shaking 不起作用
【发布时间】:2018-05-19 16:43:06
【问题描述】:

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

如果我从 webpack 文档 (https://webpack.js.org/guides/tree-shaking/) 中获取示例代码并运行它,未使用的模块/函数/其他导出被标记为未使用的和谐导出,这是预期的结果。在使用 -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 函数不会被标记为未使用,并且会保留在编译后的包中。

我错过了什么?

编辑

这是一个可以重现这种情况的演示 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 添加到预设环境选项中,Babel 不会将模块编译为 ES5,并且 Webpack 会再次将模块标记为未使用。

结论

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

【问题讨论】:

  • 你是否在你的 Babel 预设上使用 modules: false 以便模块语法不会被转换?
  • @loganfsmyth 不,我希望我是!我做了一个演示 repo 来展示我的设置:github.com/Milanzor/babel-and-treeshaking-question
  • @loganfsmyth 为了测试,将modules: false 添加到 babel 的选项中,它再次起作用(请参阅我的问题中的更新)。是什么导致 Webpack 通过 babel 转译到 ES5 后看不到未使用的代码?

标签: webpack babeljs webpack-3 tree-shaking


【解决方案1】:

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,因此不再需要此显式配置。

【讨论】:

  • 太棒了,感谢您的回复。当将modules 设置为false 时,意味着我的模块不会被转译并且不会在非主流浏览器中运行,这就是我首先使用 babel 的原因。我去看看 common-shake 插件,谢谢你的链接!
  • @myself, will not run in mainstream browsers => false,我不需要使用 Babel 将我的模块转译为 ES5,Webpack 转译以便它们在浏览器中运行!这是缺少的链接,modules: false,所以 Babel 将我的模块留给 Webpack 选择。谢谢!
  • @nodenoob 我必须找出为什么我想使用 Babel 作为加载器,因为我是 Webpack 和 Babel 的新手,但我意识到没有 Babel,Webpack 不会编译 ES6 类和其他ES6 函数到浏览器支持的代码。所以我想要 Babel 做的就是让我的代码在旧版浏览器中工作,但不要把它破坏得如此糟糕以至于摇树不再起作用。所以modules: false 为我解决了这个问题。如果我错了,请纠正我,努力学习:)
  • 是的! modules: false 使 Babel 只将模块语法传递给 Webpack,以便它可以更好地处理所有内容。
  • @Milanzor 在我的整个 Stackoverflow 生命周期中,我从未见过一个更好的例子来证明自己是@自己!
猜你喜欢
  • 2020-05-19
  • 2019-02-14
  • 2018-04-29
  • 2021-08-02
  • 2023-02-16
  • 2017-11-24
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多