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


首先,当一个包同时包含 CommonJS 和 ES 模块源并且这两个源都通过单独的主入口点或导出路径提供以在 Node.js 中使用时,就会发生上一节中描述的危险。 一个包可能被写成任何版本的 Node.js 只接收 CommonJS 源,并且包可能包含的任何单独的 ES 模块源仅用于其他环境,例如浏览器。 这样的包可以被任何版本的 Node.js 使用,因为 import 可以引用 CommonJS 文件;但它不会提供使用 ES 模块语法的任何优点。

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

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

  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. 避免或最小化上一节中描述的危害。

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.

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. The package is usable via both require and import.
  2. The package is usable in both current Node.js and older versions of Node.js that lack support for ES modules.
  3. The package main entry point, e.g. 'pkg' can be used by both require to resolve to a CommonJS file and by import to resolve to an ES module file. (And likewise for exported paths, e.g. 'pkg/feature'.)
  4. The package provides named exports, e.g. import { name } from 'pkg' rather than import pkg from 'pkg'; pkg.name.
  5. The package is potentially usable in other ES module environments such as browsers.
  6. The hazards described in the previous section are avoided or minimized.