Skip to main content

ADR003避免默认出口,优先选择已命名出口

上下文

当 CommonJS 还是主要创作格式时,最佳做法是从模块中只导出一件事,即使用module.exports = ...这与UNIX 哲学该模块将消耗 (const localName = require('the-module');无需了解内部结构)。

现在ESModules它们有许多优点,例如导出的编译时验证和标准定义的语义。 它们有一个被称为 "默认导出 "的类似机制,可以让用户import localName from 'the-module';这与import { default as localName } from 'the-module';.

不过,避免默认导出的原因有很多,之前也有其他文献对此进行过介绍:

总结:

  • 它们增加了间接性,鼓励开发者为模块创建本地名称,从而增加了认知负荷,减慢了代码理解速度:"import TheListThing from 'not-a-list-thing';`. 它们阻碍了 IDE 等工具自动重命名和重构代码。 它们助长了错别字和错误,因为导入的成员完全由消费开发者定义。 它们在 CommonJS 互操作中很难看,因为默认属性必须由消费者手动指定。 这通常被 Babel 的模块互操作所隐藏。 它们由于名称冲突而破坏了重导出,迫使开发者手动命名每个模块。

使用命名导出有助于避免重新命名符号,这样做有很多好处。 以下是一些好处:

  • 集成开发环境工具,如 "查找所有引用 "和 "转到定义 "功能 * 使用独特的符号,手动代码库搜索("grep "等)更加容易

决定

我们将停止使用默认导出,除非有绝对必要(例如[React.lazy。](https://reactjs.org/docs/code-splitting.html#reactlazy)对于那些希望永远不使用default`:

const Component = React.lazy(() =>
import('../path/to/Component').then(m => ({ default: m.Component })),
);

后果

我们将积极努力,尽可能明确地从我们的代码库中删除它们。 有连接组件吗?export const ConnectedComponent = connect(Component).

我们将添加一些工具,例如 lint 规则,以帮助用户摆脱默认导出。