【发布时间】: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