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

Is using an ES6 import to load specific names faster than importing a namespace?

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

方案一是导入某些函数:

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

选项 2 是像这样导入整个模块:

import * as R from "ramda";

我更愿意像这样引用调用函数的模块:

R.T();

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

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

我的问题与这个有点相关,但又有点不同

@Bergi 的评论是对的,我认为应该是答案。我还想指出,您可以随时在 Babel 中尝试一些东西,看看它编译成什么:click here to see what an example destructuring actually does

所以基本上,即使您只从模块中解构一个函数,整个模块都将是必需的。在我给出的 Babel 示例中,我只是从 'react' 模块中提取组件,但编译后的代码实际上只需要整个东西。 :)

TL;DR: 没关系。


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

will both 默认情况下始终引入完整的 Ramda 模块及其所有依赖项。模块内的所有代码都是 运行,使用哪种语法引用导出的绑定并不重要。使用命名导入还是命名空间导入完全取决于偏好。

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

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

要了解您的捆绑器可以进行的准确猜测,请参阅其文档。