package.json配置条件导出时main是否必须指向CommonJS文件
关于示例package.json中main字段指向CommonJS文件的原因
首先明确示例的配置内容:
// package.json { "main": "./main-require.cjs", "exports": { "import": "./main-module.js", "require": "./main-require.cjs" }, "type": "module" }
这个配置是Node.js生态里双模块兼容包的标准写法,main字段指向CommonJS文件的核心原因有3个:
main是历史兼容兜底字段:它的作用是给所有不支持exports条件导出的旧版本Node.js(v12.16.0以下、v13.0.0以下版本)提供包入口,这类版本对ES模块的支持要么是实验性的、要么完全不支持,默认只会按CommonJS规则加载main指向的文件。- 避免旧环境加载报错:如果把
main指向ES模块文件./main-module.js,在不支持ES模块的旧Node.js版本里,遇到文件里的import/export语法会直接抛语法错误,导致包完全无法使用;指向.cjs后缀的CommonJS文件,能保证所有老环境下用require()引入包时可以正常运行。 type: "module"不决定入口类型:这个配置的作用仅仅是声明当前包内后缀为.js的文件默认按ES模块规则解析,既不要求包必须对外提供ES模块入口,也不影响.cjs后缀文件固定按CommonJS解析的规则。
补充说明字段优先级:只要Node.js版本支持exports字段,加载包时就会完全忽略main字段,严格按照exports的条件规则匹配入口:
- 用
import/import()引入包时,自动加载./main-module.js的ES模块版本 - 用
require()引入包时,自动加载./main-require.cjs的CommonJS版本
这种配置的本质是做最大范围的版本兼容:新版本Node.js可以用到适配模块规范的对应入口,老旧Node.js也能拿到可正常运行的兜底入口,不会出现兼容性崩溃。
内容的提问来源于stack exchange,提问作者tonis
相关产品推荐
相关产品推荐

