export all from S2.7
中文标题:从模块全部导出
- 阶段: Stage 2.7
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年10月11日
- English original · 官方仓库
该提案针对使用 export * from 'module' 时具名导出与默认导出之间的不对称性,因为当前规范排除了默认导出。它还旨在简化需要暴露默认导出的索引模块和动态模块包装。提案移除 export * 对 default 的特殊处理,使 default 能通过 export * 作为具名导出可用,并将现有歧义解决机制应用于默认导出。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMAScript 提案:在 export * from 'module' 中包含默认导出
阶段: 2.7
作者:Nicolò Ribaudo(前作者:Guy Bedford)
审阅者: Guy Bedford, Caio Lima
规范: http://tc39.es/proposal-export-star-default/
演示文稿:
- 2016-11:为 Stage 1 进行了展示,但未达成共识(笔记)
- 2026-05:为 Stage 1 进行了展示,并达成共识(幻灯片,笔记)
- 2026-09:为 Stage 2 和 2.7 进行了展示,并达成共识(幻灯片)
动机
在当前规范中,export * from 'module' 会导出所有具名导出,但默认导出除外。
不过,在一些用例中,能够在内部私有模块中定义 default 导出,并通过 export * 将其暴露出来是很有用的。
1. 与具名导出的对称性
考虑一个模块 X,它既有具名导出,又有默认导出,并通过另一个模块重新导出。然后我们在 reexport1.js 中用显式名称重新导出该模块,并在 reexport2.js 中用 export * 重新导出:
x.js
重新导出的变体:
reexport1.js
reexport2.js
在第一个变体中,我们可以像它被显式导出那样导入默认导出:
而在 export * 重新导出的变体中,默认导出不可用:
这打破了用户的直觉,即 default 像其他任何具名导出一样是一个具名导出。
2. 创建索引模块
在 NodeJS 中,惯例是使用 index.js 作为包的主入口点。
如果我们想使用 export * 语句创建这个模块,以暴露来自子文件夹的模块,我们就无法通过这种方式导出默认导出:
index.js
如果 lib/package-core.js 包含默认导出,我们就不会将其暴露出来。
我们需要用以下方式显式导出默认导出:
index.js
以确保我们获得预期的入口点模块值。
这里的问题在于,如果我们从 lib/package-core.js 中移除默认导出,那么就会在 index.js 中得到一个 SyntaxError,提示默认导出不再存在。移除默认导出的更改需要分别在两个地方进行。
上述模式在 npm 上的 index.js 模块中也已经广泛出现,形式如下:
此时我们知道 index.js 模块将与内部模块完全一致。
3. 动态包装
重新导出默认导出的情况也可以扩展到这样的用例:我们想要动态生成一个模块包装器,暴露另一个模块的导出,而无需事先知道其导出名称。
考虑一个用例,比如 npm CDN,它允许像 https://npmcdn.com/lodash 这样的快捷 URL,然后在一个带完整版本号的 URL 如 https://npmcdn.com/lodash@4.17.2/index.js 上暴露模块。
为 https://npmcdn.com/lodash 动态生成的模块可能如下所示:
但如果存在默认导出,我们就必须提供不同的响应:
如果我们在需要时没有包含默认导出,我们可能会缺少 default,但如果在不需要时包含了它,我们就会得到错误。因此,这一限制给原本简单的服务器响应增加了一个新的静态分析问题。
提案
该提案旨在从当前规范中移除 export * 对 default 的特殊处理,以简化 export * 的对称性,并支持上文所述的更轻松的模块包装用例。
这一更改与现有规范向后兼容,并使得通过 export * 导入默认导出时不再产生语法错误,同时在这种情况下让 default 作为模块命名空间对象上的具名导出可用。
http://guybedford.github.io/proposal-export-star-default/
处理歧义
在 export * 中包含默认导出的一个顾虑是如何处理冲突,但 export * 已经被设计为能够很好地处理歧义——当模块中的两个 export * 语句解析到相同的导出名称时,会抛出 SyntaxError,如 15.2.1.16.4 12.d.ii) 中所述:
x.js
y.js
z.js
当我们尝试通过以下方式导入 name 时
我们会得到一个 SyntaxError,提示 name 有歧义。
可以通过显式指明从哪个模块导出 name 来解决这一冲突:
z.js
现在当我们从 z.js 导入 name 时,它将得到正确解析。
在这一规范更改下,同样的歧义解决过程将适用于默认导出:
会抛出 SyntaxError。
z.js
随后会通过提供显式优先级来解决该 SyntaxError,从而在处理通过 export * 产生的具名导出与默认导出之间的冲突时提供对称性。