在避免或最小化危险的同时编写双重包


【Writing dual packages while avoiding or minimizing hazards】

首先,上一节中描述的风险发生在一个包同时包含 CommonJS 和 ES 模块源文件,并且这两种源文件都可用于 Node.js,无论是通过单独的主入口点还是导出的路径提供的情况下。一个包也可能被编写为任何版本的 Node.js 仅接收 CommonJS 源文件,而包中可能包含的任何单独的 ES 模块源文件仅用于诸如浏览器等其他环境。这样的包可以被任何版本的 Node.js 使用,因为 import 可以引用 CommonJS 文件;但它不会提供使用 ES 模块语法的任何优势。

【First, the hazard described in the previous section occurs when a package contains both CommonJS and ES module sources and both sources are provided for use in Node.js, either via separate main entry points or exported paths. A package might instead be written where any version of Node.js receives only CommonJS sources, and any separate ES module sources the package might contain are intended only for other environments such as browsers. Such a package would be usable by any version of Node.js, since import can refer to CommonJS files; but it would not provide any of the advantages of using ES module syntax.】

一个包也可能在重大更改版本升级中从 CommonJS 切换到 ES 模块语法。这有一个缺点,即包的最新版本只能在支持 ES 模块的 Node.js 版本中使用。

【A package might also switch from CommonJS to ES module syntax in a breaking change version bump. This has the disadvantage that the newest version of the package would only be usable in ES module-supporting versions of Node.js.】

每种模式都有利弊,但有两种广泛的方法可以满足以下条件:

【Every pattern has tradeoffs, but there are two broad approaches that satisfy the following conditions:】

  1. 该包可以通过 requireimport 使用。
  2. 该软件包可以在当前版本的 Node.js 以及缺乏 ES 模块支持的旧版本 Node.js 中使用。
  3. 包的主入口,例如 'pkg',可以被 require 用于解析为 CommonJS 文件,也可以被 import 用于解析为 ES 模块文件。(导出的路径同理,例如 'pkg/feature'。)
  4. 该包提供具名导出,例如 import { name } from 'pkg',而不是 import pkg from 'pkg'; pkg.name
  5. 该软件包可能在其他 ES 模块环境中使用,例如浏览器。
  6. 前一节中描述的危险已被避免或最小化。