使用 ES6 导入加载特定名称是否比导入命名空间更快?

IT技术 javascript ecmascript-6 bundling-and-minification es6-modules
2021-03-04 00:49:56

例如,我发现至少有两种方法可以从 Ramda 等module中导入函数。可能还有更多的方法可以做一些非常相似的事情,比如const R = require('ramda');

选项 1 是导入某些函数:

import { cond, T, always, curry, compose } from 'ramda';

选项 2 是导入整个module,如:

import * as R from "ramda";

我更愿意引用调用函数的module,如下所示:

R.T();

但是如果使用第二个选项,它是否会引入每个 Ramda 函数,而不仅仅是我正在使用的module中使用的函数?如果使用选项 2,就发送到浏览器的内容而言,是否对实际内存使用或带宽使用有任何影响?是否有可能以某种方式做到这一点:

// invalid syntax below:
import R { cond, T, always, curry, compose } from 'ramda';
R.T();

我的问题有点与这个有关,但它有点不同 import R (ramda) into typescript .ts file

2个回答

TL;DR:没关系。


import * as … from 'ramda';
import { … } from 'ramda';

两者在默认情况下总能带来完整的Ramdamodule及其所有依赖英寸 module内的所有代码都将运行,使用哪种语法来引用导出的绑定并不重要。使用命名导入还是命名空间导入完全取决于偏好。

什么可以减少下载的文件大小和使用的内存是静态分析。在评估module后,引擎可以垃圾收集那些从无处引用的绑定。module命名空间对象可能会使这稍微困难一些,因为任何有权访问该对象的人都可以访问所有导出。但是这些对象仍然以某种方式(作为不可变的)指定,以允许对其使用进行静态分析,如果您对它们做的唯一事情是使用常量名称进行属性访问,则引擎应该利用这一事实。

任何大小优化都涉及猜测module的哪些部分需要评估,哪些不需要,并且发生在您的module捆绑器(如RollupWebPack)中。这被称为Tree Shaking,在不需要时删除部分代码和整个依赖项(被导入的任何东西使用)。无论导入样式如何,它都应该能够检测到您正在使用哪些导入,尽管在对命名空间对象执行异常操作(例如循环它或使用动态属性访问)时,它可能不得不退出。

要了解您的打包程序可以做出的准确猜测,请联系其文档。

@JoSprague 是的,我认为这很不寻常。你能举例说明你在做什么吗?
2021-04-25 00:49:56
“当对命名空间对象做不寻常的事情时,它可能不得不退出(比如循环它或使用动态属性访问)”动态属性访问有那么不寻常吗?如果动态属性访问阻止静态分析删除未使用的代码,这是否意味着命名导入是避免意外导入未使用代码分支的更好模式?
2021-05-10 00:49:56

@Bergi 在他的评论中是正确的,我认为这应该是答案。我还想指出,你总是可以在 Babel 中尝试一下,看看它编译成什么:单击此处查看解构示例实际上做了什么

所以基本上即使你只从module中解构一个函数,整个module也将是必需的。在我给出的 Babel 示例中,我只是从“react”module中提取了 Component,但编译后的代码实际上只需要整个过程。:)

导入不是解构赋值。
2021-04-24 00:49:56