为什么使用包名称从链接的本地 ES 模块包导入适用于 "main" 属性 但因 "module" 而失败

Why importing from a linked local ES modules package using the package name works with "main" property but fails with "module"

问题

pacakge.json 具有 "main" 属性 时,为什么使用 pacakge 名称从 linked 本地 NPM 包(作为 ES 模块构建)导入有效, 但当它有 "module" 属性?

时失败

设置

更具体地说,如果我们有以下设置:

  1. exporter:一个 Node.js 包,它是一个 export 的 ES 模块(例如,使用 export default)。
  2. importer:一个 Node.js 模块尝试 import exporter 导出的内容,使用 import something from 'exporter'.
  3. 使用 npm link 到本地 link exporterimporter.

然后:

为什么?我想我做错了什么?

代码

exporter

|- webpack.config.js
|- package.json
|- /src
  |- index.js
|- /dist
  |- bundle.js

webpack.config.js:

import path from "path";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default {
  mode: "development",     
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    library: {
      type: "module",
    },
  },
  experiments: {
    outputModule: true,
  },
};

package.json:

{
  "name": "exporter",
  "version": "1.0.0",
  "main": "dist/bundle.js", <-- *** NOTE THIS LINE ***
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0"
  },
  "type": "module"
}

index.js:

function util() {
  return "I'm a util!";
}
export default util;

importer

|- package.json
|- /src
  |- index.js

package.json

{
  "name": "importer",
  "version": "1.0.0",
  "type": "module"
}

index.js

import util from 'exporter';

console.log(util());

然后:

  1. 正在链接:
⚡  cd exporter
⚡  npm link
⚡  cd importer
⚡  npm link exporter
  1. 正在执行:
⚡  node importer.js 
I'm a util!

但是,如果exporterpackage.json改为:

{
  "name": "exporter",
  "version": "1.0.0",
  "module": "dist/bundle.js", <-- *** NOTE THIS LINE ***
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0"
  },
  "type": "module"
}

然后:

  1. 正在执行:
⚡  node importer.js 

失败:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'importer\node_modules\exporter\' imported from importer\src\index.js

但是为什么?

解析node_modules包时,Node.js首先检查package.json中是否有"exports"字段,如果有none则查找"main" 字段,如果是。也不在那里,它会检查是否有一个名为 index.js 的文件——尽管这种行为已被弃用并且可能会在 Node.js 的更高版本中被删除,但我建议不要依赖它并始终指定 "exports" and/or "main" 个字段。您可以查看 Node.js 文档的 Package entry points 部分以获取更多信息。

"module" 根本不是 Node.js 使用的字段,它被其他一些工具使用,所以在你的 package.json 中定义它当然没问题,但你也应该 "main" and/or "exports" 个字段。 Node.js 将使用文件扩展名来确定文件是否为 ES 模块(dist/bundle.js 使用 .js 作为扩展名,而你的 package.json 中有 "type": "module",所以你已经准备好了)。