如何在ES6模块的Node应用程序中包含CommonJS模块?

32
我有一个Node应用程序,我想以标准的ES6模块格式使用它(即在package.json中使用"type": "module"并始终使用importexport),而不需要将其转换为ES5。但我想利用一些旧的库,比如express和socket.io,它们使用CommonJS/require格式。截至2020年5月,我的选择是什么,可以将CommonJS模块合并到ES6应用程序中?

2
你可以混合使用这两个吗?我认为你不会遇到任何问题。 - Chance
4个回答

37

使用CommonJS模块的方式非常简单。 你只能从CommonJS模块中进行default导出。

import packageMain from 'commonjs-package'; // Works
import { method } from 'commonjs-package'; // Errors
这意味着所有的CommonJS出口将存在于“packageMain”对象上,您需要进入packageMain对象并使用点符号获取所需内容。
packageMain.method1()

更多信息请参考官方 Node.js 文档


6
从Node.js v14.13.0版本开始,可以使用带限定符的CommonJS模块导入。 - xamgore

14
自 Node 13.10 起,有另一种选择,最具前瞻性的选择是:
在您想使用的 CommonJS 库的存储库中提交问题,说服维护者 发布 双重包(ESM + CommonJS),使用 条件导出
对于使用 TypeScript 编写的库,生成双重包很容易,不需要 Babel、Rollup 或任何其他工具。以下是我在 local-iso-dt 中的做法: package.json 的相关部分:
{
  "name": "local-iso-dt",
  "version": "3.1.0",
  "description": "...",
  "type": "commonjs",
  "exports": {
    "node": {
      "import": "./index.mjs",
      "require": "./index.js"
    },
    "default": "./index.mjs"
  },
  "main": "index.js",
  "files": [
    "index.ts",
    "index.mjs",
    "index.js"
  ],
  "scripts": {
    "clean": "rm index*.js index.mjs",
    "prepublishOnly:cjs": "tsc index.ts --esModuleInterop --removeComments",
    "prepublishOnly:esm": "tsc index.ts -t ES2015 --types node && mv index.js index.mjs",
    "prepublishOnly": "npm run prepublishOnly:esm; npm run prepublishOnly:cjs"
  },
  "devDependencies": {
    "typescript": "^4.0.2"
  },
}
会手动重命名输出,因为TypeScript目前无法直接生成.mjs输出,而--outFile与ES模块不兼容。 exports 块有“条件导出”,使得使用ES模块转译的TypeScript代码可以使用命名导入。TypeScript不直接支持.mjs输入文件
对于这个简单的模块,不需要tsconfig.json

4
伊万的回答很有帮助,但我也应该指出,因为我使用的是 node 12.16.3 版本,所以我还需要在 package.json 的启动脚本中添加 --experimental-modules 标志。
"type": "module",
"scripts": {
    "start": "node --experimental-modules --experimental-json-modules server.mjs",
}
  • "type": "module" 告诉 Node 使用 ES6 模块
  • .mjs 文件扩展名进一步明确了我们正在使用模块化的 JavaScript 文件
  • --experimental-modules--experimental-json-modules 可以让你在 Node 12 版本中使用 import

然后我就可以像这样做:import express from 'express';(其中 express 4.17.1 是一个 CommonJS 模块),并且它可以正常工作。


经过8个小时的努力,几乎尝试了所有的方法...谢谢你,我的救星。 - undefined

1
确保所讨论的模块具有一个导出你想要importrequire的代码的index.js文件。
package.json中,在dependencies属性下添加:
"myCustomModule":"file:./path/to/myCustomModule"

完成此操作后,运行npm install
完成后,在项目的node_modules/目录中查看,您将看到一个名为myCustomModule的目录。
现在,在任何项目文件中,您可以像导入或要求其他mode_module一样导入该代码。

一个 commonjs 模块中,index.js 如何导出你想要引入的代码? - joegomain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接