【问题标题】:Webpack Importing a javscript function from a module also imports every other statements and functions in that moduleWebpack 从模块导入 javascript 函数也会导入该模块中的所有其他语句和函数
【发布时间】:2020-01-31 04:55:02
【问题描述】:

我正在为我的项目使用 webpack。

假设我有一个dep.js 文件,其中包含以下代码

export function abc() {
   var a = 10;
}

console.log(100);

function xyz(){
   var b = 11;
}

xyx();

我有一个main.js 文件,其中包含以下代码

import {abc} from './dep.js';

根据导入导出的逻辑,应该只导入函数abc。 但是当我在控制台中检查源代码时,我发现

--> 所有其他语句和函数,如console.log(100)function xyx 也被导入

--> 以及dep.js中通过xyz()调用函数的效果也显示了main.js中的效果

为什么会这样?

【问题讨论】:

  • 有时,您可以增加pass option 来增加摇树效果。

标签: javascript webpack ecmascript-6


【解决方案1】:

默认情况下,这就是模块的工作方式。如果模块的任何部分至少被导入一次,整个模块会运行它的所有顶级代码。

可以删除在 Webpack 中无法使用 tree shaking 运行的死代码,但显示的模块没有任何死代码 - 它有一个导出的函数,可以使用,它的代码是在顶层运行并调用(console.logxyx 的声明和xyx 的调用)。

如果您导出了模块中其他地方没有使用的东西,它可能会随着摇树摇晃而被丢弃,例如:

export function abc(){
   var a = 10;
}
export function def(){
   var a = 10;
}

这里,如果def没有被导入或在别处使用,它可以被自动删除。

(另请注意,函数定义在它们之后需要()s,即使它们不带参数)


这就是为什么我几乎总是只导出函数 - 最好避免编写对模块顶层有副作用的代码,因为这样只导入模块就会导致在那些副作用中(就像你在这里看到的那样)。当你有一个单一的入口点(例如main.js)来导入它需要的函数然后调用它们时,通常更容易构建代码。如果每个模块都将带有副作用的代码作为顶层的一部分运行,那么事情很快就会变得非常混乱和难以管理。 (这种技术也恰好可以改善 tree-shaking,但这只是一个附带的好处)

【讨论】:

  • 说得好。嘿,你觉得在my example,如果我export let createCounterFunction,会更容易发生摇树?
  • abc 中缺少 () 是一个错字。谢谢你让我明白这一点。还有一件事。假设如果我想从dependency.js 导入main.js 中的函数abc() 并期望它在导入后不手动执行main.js 来执行abc(),我应该通过abc() 在@ 中执行函数abc 987654340@ 因为它会像你说的那样运行所有顶级代码?还是有更好的方法?
  • @LonnieBest 我只知道 tree-shaking 工作原理的基础知识,但我对它或它的机制没有经验,抱歉 - 不知道
  • @Jake 如果你想要一个在导入时有副作用的模块(并且不必被调用),你可以这样做——想想@987654341 @ 在您的问题中,除了没有 abc 功能 - 而是使用 import 'dep.js';。它可以工作,但我不会经常这样做,因为它会使控制流更加不透明,并使重构更加困难。 (无论是将它放入一个函数然后执行该函数,还是将所有代码放在顶层,如果您试图让代码在没有导入器显式调用函数的情况下运行,都不会产生影响)
  • @Jake :当我想确保一个函数被省略时,当它不被使用时,我将该函数放在它自己的文件中(单独)。这总是有效的;每次不导入时都会省略。
猜你喜欢
  • 2022-01-14
  • 2019-08-01
  • 2022-11-11
  • 1970-01-01
  • 2015-03-05
  • 2018-10-30
  • 1970-01-01
  • 2023-03-29
  • 2017-05-31
相关资源
最近更新 更多