{
"main": "./index.js"
}
main
字段是模块的主要入口点。当进行 require
导入模块时,会查看 main
字段,然后返回模块中导出的对象。
main
应该是一个相对于包文件夹根目录的模块。
对于大多数模块来说,有一个主入口就够了。
如果 package.json 中没有设置 main
,模块的主入口默认指向包根文件夹中的 index.js
文件。
CommonJS 的案例
下面看看 main
字段设置模块主入口的例子,此例子的目录结构如下:
util/package.json
指定了 util
模块的主入口为 main.js
,util/package.json
代码如下:
{
"name": "util",
"main": "./main.js"
}
util/main.js
文件的代码如下,导出了 subtract
函数:
function subtract(a, b) {
return a - b;
}
module.exports = {
subtract: subtract,
};
util/index.js
文件的代码如下,导出了 add
函数:
function add(a, b) {
return a + b;
}
module.exports = {
add: add,
};
app.js
文件的代码如下:
const util = require("./util");
console.log(util.subtract(2, 1));
然后在命令行终端使用 Node.js 运行 app.js
文件,正常输出 1
:
可以发现,当 package.json 的 main
字段设置为 ./main.js
后,require("./util")
会在 util
文件夹下的 main.js
中加载模块。
ESM 的案例
上面的例子是 CommonJS 的,而如果是 ES 模块,则会报 ERR_UNSUPPORTED_DIR_IMPORT
的错误:
不过 ERR_UNSUPPORTED_DIR_IMPORT
的错误可以通过使用 --experimental-specifier-resolution=node
标志解决:
node --experimental-specifier-resolution=node app.js
ES 模块的例子的目录结构为:
package.json
文件内容如下,主要告知当前是 ES 模块:
{
"type": "module"
}
app.js
文件内容如下:
import { subtract } from "./util";
console.log(subtract(2, 1));
util/package.json
文件内容如下,主要指定了当前是 ES 模块,并且模块的主入口为 ./main.js
,这样当 import
这个模块时,则会找到 ./main.js
文件,返回模块导出的内容。
{
"name": "util",
"type": "module",
"main": "./main.js"
}
util/main.js
文件内容如下:
function subtract(a, b) {
return a - b;
}
export { subtract };
util/index.js
文件内容如下,由于使用 package.json
中的 main
字段设置了新的入口,所以 import
util
模块时,不会找到 util/index.js
中来:
function add(a, b) {
return a + b;
}
export { add };
然后在命令行终端运行 app.js
文件,上文也说过,会报 ERR_UNSUPPORTED_DIR_IMPORT
的错误:
如果加上 --experimental-specifier-resolution=node
的标识,就可以正常运行了:
总结
package.json
文件中的 main
字段用于指定模块的入口文件,即当其他模块通过 Node.js
的 require()
函数或现代 JavaScript 的 import
语句来引用这个包时,默认加载的文件。
当使用 import
时,在 Node.js 中要指定 --experimental-specifier-resolution=node
标识,否则运行代码时,会报 ERR_UNSUPPORTED_DIR_IMPORT
的错误。