Express Node 的 CommonJS 与 ES 模块

Gle*_*kin 1 node.js express

谁能解释一下 Node Express 应用程序的最佳方法是什么:CommonJS 或 ES 模块?在官方文档中显示使用了 CommonJS 模块,但是有很多讨论指出使用 ES 模块进行后端开发。所以我想征求一些意见。

提前致谢!

jQu*_*eny 6

Node.js 官方文档非常擅长解释两种不同类型的模块系统。CommonJSESM

Node.js 设计模式中有一个非常好的章节,第 2 章:模块系统(2020),描述了 CommonJS 的来源。它源于在无浏览器环境中为 JavaScript 提供模块系统的需求,因为除了 AMD 和 UMD 计划之外,不存在这种模块系统,并且不依赖资源urls和标签。<script>它很成功,因此受到欢迎。

感谢 ES2015 官方提案,我们现在有了 ECMAScript 模块,它试图在服务器端和浏览器环境中协调模块的管理。

帮助您做出决定的要点是:

  1. CommonJS使用该require函数来加载模块并且是同步的。因此,当您分配一个模块时module.exports,它也必须是同步的。如果您的模块中有异步阶段,那么您可以导出未初始化的模块,但使用require将意味着它有可能无法在初始化之前在需要它的代码中使用。
  2. ES模块使用import关键字来加载模块。它们是静态的,因此需要在每个模块的顶层进行描述,并支持异步加载模块。ES 模块有助于对依赖树进行静态分析,使死代码消除(tree shake)更加有效。
  3. ES 模块在严格模式下隐式运行(无法禁用)。在许多人看来,这是一件好事,因为它强制执行良好的编码实践。
  4. 在 CommonJS 中,您可以使用帮助__filename__dirname. 在 ES 模块中,您需要采取解决方法才能获得相同的功能,如下所示:
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
Run Code Online (Sandbox Code Playgroud)
  1. 您可以使用以下命令在 CommonJS 中动态加载模块require
let usefulModule;
if (process.env.DEV === true) {
   usefulModule = require('./utils/devmodule')
} else {
   usefulModule = require('./utils/prodmodule')
}
Run Code Online (Sandbox Code Playgroud)
  1. 在 ESM 中使用importas 函数:
let lib;
if (process.env.DEV === true) {
   lib  = await import('./utils/devmodule.js');
   
} else {
   lib  = await import('./utils/prodmodule.js');
}
const usefulModule = lib.usefulModule;
Run Code Online (Sandbox Code Playgroud)

在多年的编程生涯中,我注意到的一件事是语言和库的不断发展。我观察到 Node 包文档中的变化越来越大,以 ESM 格式提供了越来越多的示例。CommonJS 仍然是npm 上的主导选项,但它告诉我生态系统正在慢慢从 CommonJS 转向 ESM。也许它们会齐头并进,但这就是进化的本质,一个人会成为其他人的主导者。我从事的所有项目都使用 ESM 方法。祝你决定好运。