【问题标题】:`export` or `import` behaving different in webpack production than in development mode`export` 或 `import` 在 webpack 生产和开发模式中的行为不同
【发布时间】:2022-01-07 17:20:58
【问题描述】:

我试图弄清楚为什么应用程序(Vuejs3、webpack 5、Babel 7)在生产模式和开发模式下的行为不同。出于某种原因,在生产模式下,导入和导出的工作方式不同(即根本不导入文件,即它们的代码在导入期间没有运行)。

这是在开发模式下工作的结构:

+- foo/
| +-- index.js
|     
|     export {default as Component} from './comp';
|     export {default as SomethingElse} from './comp2';
|
| +-- comp.vue
|
|     alert('hey there!');     
|     export default {...component here...}
|
+- main.js
   
   import './foo';

这在开发模式下一切正常,但在生产模式下根本不行。我似乎comp.vue 中的代码从未被执行,因此组件没有被导入/注册。我尝试在index.js 中使用re-exporting/aggregation,但这并没有改变任何东西。

如果我将main.js 更改为import {Component} from './foo',那么一切正常。然而,import 'file' 模式被频繁使用,以至于我很难改变它(它在开发模式下工作)。

实现这项工作的另一种方法是在生产中将源映射设置为eval-cheap-source-map(而不是source-map),这与开发中使用的源映射方法相同。相反,如果我在开发模式下将 source map 更改为source-map,则组件加载成功。

这使我得出这样的结论,即 webpack 在生产中处理导出/导入的方式与开发中不同(源映射观察只是一个观察,但值得注意)。我对为什么会发生这种情况感到有些困惑,因此希望您能分享任何经验。

注意

这可能是某些生产模式优化步骤的问题。有什么办法可以禁用它们(所有这些都看看这是否是一般问题,然后禁用/重新启用它们的部分以找到“罪魁祸首”?)

【问题讨论】:

  • 是的,对我来说,这看起来像是摇树死代码消除优化。除了禁用它之外,可能还有一种方法可以注释 alert() 不被删除的行。最佳实践是完全不依赖导入模块的副作用,而是导入一个函数(执行alert())并从main 显式调用它。
  • 我可以确认这是问题所在。我将optimization: {minimize: true, minimizer: [new TerserPlugin(), new CssMinimizerPlugin()]} 更改为optimization: {minimize: false}} 并且一切正常(除了巨大的文件大小;-))。
  • 有趣的评论回复:“副作用”。实际上,我在文件中大量使用这种模式来设置代码。它还用于注册组件,这很好,因为它将组件注册的行为保留在组件本身中(只需要导入文件)。但是我可以看到这会如何绊倒代码优化器。是否可以配置这部分优化(即不要消除导入 - 只导入所需的代码,因此文件大小应该不是问题)?
  • webpack.js.org/guides/tree-shaking 不确定是否有办法在文件本身中标记副作用(在注册调用上)
  • optimization: {sideEffects: ...} optimization: {usedExports: ...} 对于任何值组合都没有任何效果。只有从 minimizers 中删除 new TerserPlugin() 才能避免这种情况发生。我阅读副作用选项的方式也是默认情况下不会删除这些导入,所以我想知道是否真的是别的东西,因为这种情况下的摇树应该被默认禁用(这是有道理的,因为它过度攻击性的)。

标签: javascript vue.js webpack


【解决方案1】:

在多次尝试在 webpack 配置中修复这个问题后,我得到了这个配置:

optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserPlugin({
        terserOptions: {
          compress: {
            unused: false
          }
        }
      })
    ]
  },

unused (default: true) -- 删除未引用的函数和变量(简单的直接变量赋值不算作引用,除非设置为“keep_assign”)

这似乎可以避免在使用重新导出时剔除副作用代码。我还没有弄清楚为什么代码被认为是无副作用的(据我所知,这不是默认值)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2019-11-26
    • 1970-01-01
    相关资源
    最近更新 更多