前言
作为一个 package 的作者,或多或少都会接触到 package 的文件入口的问题。
在使用前端框架创建项目工程的时候,都会有一个单一入口文件,告诉我们或者浏览器或者构建工具,入口在哪里。
编写一个 package 也不例外,也需要告知 Nodejs 或者构建工具,这个 package 的入口在哪里?
字段讲解
main
这是普遍开发者都知道的一个字段,定义这个 package 的入口文件位置。
-
在不支持 ES6 的 Nodejs 中,它指向的就是 CommonJs 模块系统的入口位置。
-
在 Nodejs 支持 ES6 的版本中,只要显示定义
"type": "module"
,那么它指向的就是 ESM 模块系统的入口位置
module 字段
可能很多人对于这个字段的含义都有些误解,会认为它就是 ESM 模块系统的入口位置。
import xxx from 'xxx'
通过以上的导入方式就能命中 module 字段所指向的文件位置,进行模块的导入。这在使用了构建工具的项目中是没有问题的,可以正常执行,因为常见的构建工具都能识别它。
但如果在一个 package 中,如果 main 字段指向一个 CJS 文件,而 module 字段指向一个 ESM 文件,直接在开启了 ESModule 的 Nodejs 中通过按需加载的 import 方式导入,那么将会报错
SyntaxError: Named export 'xx' not found. The requested module 'xx' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'xx';
const { b, a } = pkg;
上述报错信息可以说明,我们引入的文件是一个 Commonjs module 文件,而 module 指向的是 ESModule 文件。说明 Nodejs 目前(v18.7.0)还不能识别 module 字段
官方文档是这样子描述的:
Dual CommonJS/ES module packages
Prior to the introduction of support for ES modules in Node.js, it was a common pattern for package authors to include both CommonJS and ES module JavaScript sources in their package, with package.json
"main"
specifying the CommonJS entry point and package.json
"module"
specifying the ES module entry point. This enabled Node.js to run the CommonJS entry point while build tools such as bundlers used the ES module entry point, since Node.js ignored (and still ignores) the top-level "module"
field.
Node.js can now run ES module entry points, and a package can contain both CommonJS and ES module entry points (either via separate specifiers such as 'pkg'
and 'pkg/es-module'
, or both at the same specifier via Conditional exports). Unlike in the scenario where "module"
is only used by bundlers, or ES module files are transpiled into CommonJS on the fly before evaluation by Node.js, the files referenced by the ES module entry point are evaluated as ES modules.
保守估计应该不会再去解决这个问题,毕竟因为已经有了 exports
字段。
exports 字段
在支持 ES6 的 Nodejs 版本中,就开始支持 exports 字段了。
具体 exports 字段的解释和用法,我觉得可以参考阮一峰老师的 ES6 入门一书。