【问题标题】:How to include commonjs module in ES6 module node app?如何在 ES6 模块节点应用程序中包含 commonjs 模块?
【发布时间】:2020-08-16 08:26:18
【问题描述】:

我有一个节点应用程序,我想以标准 ES6 模块格式(即"type": "module" in the package.json,并始终使用importexport)而不转译为 ES5。但我想利用一些较旧的库,例如使用 CommonJS / require 格式的 express 和 socket.io。将 CommonJS 模块组合到 ES6 应用程序中,我有哪些选择(截至 5/2020,Node 12.16.3)?

【问题讨论】:

  • 两者可以混搭吗?我认为你不会有任何问题。

标签: javascript node.js ecmascript-6 es6-modules commonjs


【解决方案1】:

确保有问题的模块有一个index.js,可以将您想要的代码导出到importrequire

package.jsondependencies 属性下添加以下内容:

"myCustomModule":"file:./path/to/myCustomModule"

完成此操作后运行npm install

完成后查看项目根目录的node_modules,您将看到一个名为myCustonModule 的目录。

现在,在任何项目文件中,您都可以像在任何其他 mode_module 中一样使用 importrequire 该代码

【讨论】:

    【解决方案2】:

    使用 CommonJS 模块非常简单。 您只能从 CommonJS 模块执行 default 导出。

    import packageMain from 'commonjs-package'; // Works
    import { method } from 'commonjs-package'; // Errors
    

    这意味着所有 commonjs 导出都将存在于 packageMain 对象上,您需要在 packageMain 对象中 以获取您需要的内容。

    packageMain.method1()
    

    更多信息在official nodejs docs

    【讨论】:

    • 从 nodejs v14.13.0 开始是 possible to use 合格的 CJS 模块导入。
    【解决方案3】:

    Ivan 的回答很有帮助,但我还应该注意,因为我使用的是节点 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 让您在节点版本 12 中使用 import

    然后我就可以做import express from 'express';(其中 express 4.17.1 是一个 CommonJS 模块)之类的事情,而且效果很好。

    【讨论】:

      【解决方案4】:

      从Node 13.10开始,还有一个选择,最有前瞻性的一个:

      在您想要使用的 CommonJS 库的 repo 中提交问题,persuading the maintainers 以发布 dual packages (ESM + CommonJS),使用 conditional exports

      对于用 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"
        },
      }
      

      prepublishOnly:esm 手动重命名输出,因为 TypeScript can't yet generate .mjs output directly--outFile 不适用于 ES 模块。

      exports 块具有“conditional exports”,它启用使用 ES 模块转译的 TypeScript 代码,以使用命名导入。TypeScript doesn't directly support .mjs input files

      这个简单的模块不需要tsconfig.json

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-19
        • 2015-11-21
        • 2015-09-07
        • 2015-08-19
        • 1970-01-01
        • 1970-01-01
        • 2021-04-16
        • 1970-01-01
        相关资源
        最近更新 更多