【问题标题】:Why can't both require('foo') and ECMAScript exports be used in the same project?为什么不能在同一个项目中同时使用 require('foo') 和 ECMAScript 导出?
【发布时间】:2020-11-25 13:45:50
【问题描述】:

刚开始使用 JavaScript,我遇到了一个我无法解释的问题。我只是想了解不同的导入选项。

我有:

main.js
utils.js
package.json

utils.js

// this is simply an exemple from the node.js docs
const readline = require("readline");
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question("What is your name ? ", function(name) {
    rl.question("Where do you live ? ", function(country) {
        console.log(`${name}, is a citizen of ${country}`);
        rl.close();
    });
});
export {rl}

package.json

{
  "name": "sandbox",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
   "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-preset-env": "^1.7.0",
    "babel-register": "^6.26.0"
  }
}

main.js

import {rl} from './utils.js'

// do stuff with rl, but the import fails

使用上面的代码,require(...) is not defined 如果我尝试直接运行 utils.js。我需要删除导出语句和“类型”:“模块”。如果我将 utils.js 重命名为 utils.mjs,那么我会得到“require is not defined”。所以基本上我不能同时拥有 require(...) 和使用导出。

如果我运行 main.js,那么它会说 utils.js 不提供名为 rl 的导出(但确实提供了!)。

为什么 "type":"module" & require(...) 语法不能共存?如果我使用的包已经使用了 require() 语法,那么这是否意味着我的项目的其余部分不能使用 ECMAScript 导出?

【问题讨论】:

    标签: javascript node.js ecmascript-6 import


    【解决方案1】:

    为什么"type":"module" & require(...) 语法不能共存?

    They can。在 ESM 模块(JavaScript import/export 语法)中,您可以从 CJS 模块(较旧的 CommonJS 模块系统)导入。如果您需要其他方式不可用的功能(例如导入 JSON),也可以使用 createRequire

    如果我使用的包已经使用了 require() 语法,那么这是否意味着我的项目的其余部分不能使用 ecmascript 导出?

    不,这仍然是可能的,但如果您完全转换为 ESM(或者根本不使用 ESM - 例如,如果您避免同时使用两者),生活会简单得多。最接近的package.json 中的type 设置决定了导入的内容是默认使用ESM 还是CJS。你可以(例如)有一个旧东西的目录,其中有一个最小的package.json,其中有"type": "commonjs",而你的项目的主要package.json"type": "module"

    项目根/ + package.json w/“类型”:“模块” + foo.js - ESM 模块 + bar.js - ESM 模块 + 遗产/ + package.json w/“类型”:“commonjs” + baz.js - CJS 模块

    或者,您可以在主package.json 中使用"type": "commonjs"(或根本没有type)并在ESM 模块上使用文件扩展名.mjs。 (我不喜欢这个,但 Node.js 支持它。)

    更多内容请关注Node.js ESM documentation

    【讨论】:

    • 哦,我明白了。我不太了解那里的动态,也没有完全阅读节点的文档。我曾认为这比我可能需要的 hello-world-ish 程序要详细得多。从 Python 的背景来看,实际上只有一个导入机制,而且从来没有考虑过太多的想法。感谢您的精彩解释。
    • @logicOnAbstractions - 我的荣幸!如果它是 Hello, World,只需使用 "type": "module" 就可以了——您可以使用新语法导入所有 Node.js 和 npm 包。但是,是的,在现有项目中,我们暂时处于从旧机制过渡到新机制的痛点。 :-)
    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 2015-11-30
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 2014-05-25
    相关资源
    最近更新 更多