CommonJS 'require' 仍在使用还是已弃用?

Is CommonJS 'require' still used or deprecated?

当前Javascript采用ES6的import作为导入模块的标准方式。 但是,我有时会看到使用 CommonJS require 而不是 import.

的代码

我一开始想两个能不能一起用,但是好像两个不能互换。 (相关

那么,CommonJS 'require' 是否仍在项目中使用?或者它正在慢慢消亡,只需要维护遗留代码?

CommonJS 可能会在 nodejs 中得到长期支持,因为仍有数百万行代码使用它编写。是nodejs中独创的模块加载机制。它没有被弃用。

使用 importexport 的 ESM 模块(ECMAScript 模块)是新的 Javascript 模块标准,我们可以预期 nodejs 会一直支持这些模块Javascript 标准(可能永远)。

这两个模块标准并不完全兼容,因此在同一个项目中混合和匹配可能会导致您必须学习如何处理的复杂情况。

新项目

如果我今天开始一个新项目,我会选择使用 ESM 模块编写我的代码,因为这是语言和 nodejs 的未来发展轨迹。而且,如果您需要与其他模块向后兼容,您仍然可以将 CommonJS 模块加载到 ESM 模块中,但您必须知道如何正确地做到这一点——混合和匹配模块类型并不总是无缝的。

当 nodejs 首次支持 ESM 模块时,与 CommonJS 模块的互操作性不是很完整,造成了一些困难。对于最新版本的 nodejs,您可以从 ESM 模块加载 CommonJS 模块,反之亦然——您只需要使用正确的技术即可。这使得现在从 ESM 项目工作比 nodejs 中的 ESM 支持首次出现时更加可行,因为您仍然可以访问 NPM 中仅支持 CommonJS 的库。

另请注意,NPM 中越来越多的库支持从任一模块类型直接加载,因此无论您的项目是 CommonJS 还是 ESM,它们都同样易于使用。

随着时间的推移,我希望 NPM 上任何积极开发的共享模块最终都将支持直接加载为 ESM 模块。但是,我们正处于这个过渡时期,其中许多人尚未实施,或者在实施新的加载方案(带有自己的和不同的规则集)方面存在特殊挑战。同时,您仍然可以将 CommonJS 模块加载到 ESM 项目中。

现有的 CommonJS 项目

如果我有一个现有的 CommonJS 项目,我不会花任何时间考虑将其转换为 ESM,因为 CommonJS 仍然得到广泛支持,我的开发人员时间可能最好花在添加功能、测试、修复错误等...而不是转换模块格式。

互操作性

要知道的重要互操作性事情之一是您可以通过几种不同的方式从 ESM 模块加载 CommonJS 模块:

  1. 使用静态导入:import { callMeCommon } from '../otherProject/common.js';
  2. 使用动态导入import(someFile).then(...)
  3. 通过使用 module.createRequire(import.meta.url) 然后使用 require() 函数来加载您的 CommonJS 模块。

您也可以使用动态 import('someModule').then(...) 从 CommonJS 模块加载 ESM 模块,但它不像 require() 那样是同步的,因此必须以不同的方式处理。

了解 ESM 模块没有 CommonJS 模块所具有的一些 nodejs 细节也很有用。没有自动 __dirname__filename 告诉您这个文件是从哪里加载的。相反,您必须从 import.meta.url 中解析出这些值并计算它们。所以,还是可以得到那些信息的,只是没有以前那么方便了。

另一方面,ESM 模块有一些 CommonJS 没有的功能,例如顶层 await,这些功能非常有用。

您的具体问题

So, is CommonJS 'require' something that is still used in projects?

是的,现在还在用

Or is it slowly dying and needed only for maintaining legacy codes?

[截至 2022 年初的评论] 我不会说它正在消亡,因为 NPM 上很少有项目仍然不支持 CommonJS。事实上,当一个项目发布一个不再支持 CommonJS 的新版本时,它会给他们的用户群带来很大的问题(我们在 Whosebug 上看到了其中的一些问题),因为 CommonJS 项目仍然非常流行,而且人们不熟悉如何加载不同的模块类型。

所以,我想说的是,我们仍处于从 CommonJS 到 ESM 的过渡的早期阶段,更像是 ESM 得到越来越多的采用,而不是 CommonJS 正在消亡。我敢猜测 NPM 上的大多数模块在未来几年内将支持从这两种模块格式直接加载。

转译

最后,开发人员经常使用转译来允许他们使用最新的语法和功能编写代码,但使用转译器将代码转换回可在任何地方运行的较低的公分母。这也可以用于模块架构(在 ESM 中编写代码,转换为 CommonJS)。

一些有趣的参考资料

What does it take to support Node.js ESM?

Hybrid npm packages (ESM and CommonJS)

Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

All you need to know to move from CommonJS to ECMAScript Modules (ESM) in Node.js