【问题标题】:Webpack including unused exports in final bundle (not tree shaking)Webpack 包括最终包中未使用的导出(不是摇树)
【发布时间】:2018-07-13 22:31:43
【问题描述】:

我有一个设置,其中库的 index.js(主入口点)导出库中的所有内容......所以它的设置如下:

export * from "./mod1"
export * from "./mod2"
// etc...

(take a look)

当我从该入口点导入 1 个导出的库时,看起来 Webpack 无法对输出进行树状抖动。运行webpack -p 实际上是将整个库包含在包中,尽管只导入了一个导出。运行webpack(非生产包)确实会在整个文件中显示unused harmony export ....(167 次),但为什么它们没有被删除?

我有一个显示此问题的测试设置:https://github.com/purtuga/webpack-bundle-test

希望某人(比我聪明 :))可以帮助确定我做错了什么。

/保罗

【问题讨论】:

  • 您找到更好的解决方案了吗?我面临着完全相同的问题。
  • 我感觉迁移到了 Webpack 4,我想我不再有这个问题了 - 但是:我没有绕回它来验证(使用我设置的测试项目)。如果我有时间,我会这样做并在这里报告。
  • 我已针对我的问题打开了一个新帖子:stackoverflow.com/questions/55320774/…
  • 感谢@Apidcloud。我也会关注这个问题,并且还在 Twitter 上分享了你的问题,看看我们是否有更广泛的社区来关注它。

标签: webpack webpack-3 tree-shaking


【解决方案1】:

当您在没有转换(如 Babel)和缩小(如 UglifyJS)的情况下捆绑应用程序时,您会得到:未使用的和声导出

现在 Webpack 2+ 只标记未使用的代码,不会将其导出到模块中。它会提取所有内容并为缩小库留下未使用的代码。

您可以为此使用UglifyJS 和 babel。 UglifyJS 还不支持 Javascript ES2015+ 的新语言特性。您将需要 Babel 将代码转译为 ES5,然后使用 UglifyJS 清理未使用的代码。

你需要 .babelrc 文件:

我们必须告诉预设(在我们的例子中为babel-preset-env)跳过模块转译。

{
  "presets": [
    ["env", {
      "loose": true,
      "modules": false
    }]
  ]
}

以及对应的 webpack 配置:

module: {
  rules: [
    { test: /\.js$/, loader: 'babel-loader' }
  ]
},

plugins: [
  new webpack.LoaderOptionsPlugin({
    minimize: true,
    debug: false
  }),
  new webpack.optimize.UglifyJsPlugin({
    compress: {
      warnings: true
    },
    output: {
      comments: false
    },
    sourceMap: false
  })
]

Babili 是更好的选择,因为 Babili 会在转译之前删除未使用的代码。在降级到 ES5 之前发现未使用的类要容易得多。 Tree-shaking 也适用于类声明,而不仅仅是函数。

你需要:

npm install babili babili-webpack-plugin --save-dev

在您的 webpack 配置中使用以下插件,如下所示:

plugins: [
  new BabiliPlugin()
]

还有一种使用 babili 作为预设的优化方式。您可以参考他们的网站以将其用作 babel-loader 的预设。

【讨论】:

  • 感谢您的回复...但这无济于事。是的,我确实了解摇树实际上是如何完成的..您在上面描述的所有内容在我的示例中都是正确的(看看我提供的测试 git repo) - 所以我期待“死代码”在包裹被缩小了(webpack -p) - 但事实并非如此......我真的很难过这个......
【解决方案2】:

我克隆了你的“webpack-bundle-test”,这就是我所做的。

  1. https://github.com/purtuga/common-micro-libs 复制了“common-micro-libs”src 文件夹。
  2. 将mod3.js中的代码修改为:import { objectExtend } from "./common-micro-libs" export default mod3 = objectExtend({}, { text: "module 3" });

  3. 我在本地跑了webpack,发现了167个“未使用的和谐”cmets。

  4. 使用webpack -p 我得到以下结果:
  5. 将 mod3.js 中的代码更改为 import objectExtend from "./common-micro-libs/jsutils/objectExtend.js" export default mod3 = objectExtend({}, { text: "module 3" });
  6. 通过上述更改,我可以看到捆绑包大小的以下减少

我相信在导入依赖项时,最好只从库中导入必要的功能/组件,这样会更有效地打包在包中。 我无法解释为什么会这样,尽管我在使用 lodash 时在项目中导入实用程序时遵循了相同的原则,并且效果很好。 你能运行测试并告诉我吗?

【讨论】:

  • 嗨 Priyesh - 感谢您的回复。我已经从单个 lib-name/src/.../ 文件导入依赖项有一段时间了——所以我知道这是可行的。但是我试图通过仅使用库包名称来保持from 的右侧简短,并从那里检索命名的导入(import { foo } from "lib-name" - 那就是我发现这个问题的时候 - 我正在寻找理解为什么会发生。我不确定是谁的错:是 webpack 以它在包中定义未使用的harmony 导入的方式(因此 Uglify 无法删除它们)还是 Uglify?谢谢你的尝试
  • 你找到更好的方法了吗?我有同样的问题:/
  • webpack 4's treeshaking 中,您不能在 package.json 中设置“sideEffects”属性。这些为 webpack 编译器提供了关于“死代码”的提示
猜你喜欢
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 2021-07-08
  • 2016-11-17
  • 2019-12-29
  • 2020-06-10
相关资源
最近更新 更多