ES6 Node.js中导入'.json'扩展名会抛出错误

113
我们正在尝试使用ES6与Node.js的新方式导出和导入模块。从package.json文件中获取版本号对我们很重要。以下代码应该可以实现这一点:
import {name, version} from '../../package.json'

然而,在执行时会抛出以下错误:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".json" for T:\ICP\package.json imported from T:\ICP\src\controllers\about.js

我们是否遗漏了什么?
扩展名为.json的文件不被支持吗?
在使用Node.js 13+时,是否有其他获取此信息的方法?


你在那个路径下有一个json文件吗?你尝试过其他导入方式,比如 import pkg from ('../../package.json') 吗? - palaѕн
是的,.json 文件位置正确。 - DarkLite1
5个回答

163

从 Node.js 版本 17.5.0 开始,可以使用 导入断言 来导入 JSON 文件:

import packageFile from "../../package.json" assert { type: "json" };

const {
    name,
    version
  } = packageFile;
  • assert { type: "json" } 为必填项。
  • import 声明中直接进行解构赋值,如 { name, version } 是不可行的。
  • JSON 文件的内容被导出为默认导出,因此需要从 default 中导入。

动态导入的版本如下:

const {
    default: {
      name,
      version
    }
  } = await import("../../package.json", {
    assert: {
      type: "json"
    }
  });

由于导入断言JSON模块最近才晋升为第三阶段,旧版本的Node.js可能支持旧语法。

根据MDN上有关import声明动态import的兼容性表,旧版本的Node.js(16.0.0 – 16.14.0 和 17.0.0 – 17.4.0)存在不同程度的支持:

  • 这些版本需要使用 --experimental-json-modules 标志:

node --experimental-json-modules about.js
  • 某些版本不支持动态import中的导入断言

  • 某些版本不支持"json"类型,具体而言

  • 某些版本依赖于较旧的建议,该建议尚未指定assert语法


  • 1
    嗨 Idder,加上标记 . yarn run dev --experimental-json-modules 后,我也遇到了同样的错误。这是用于运行我的项目的脚本。 - Hemant
    7
    每次都加那个标记很烦人。能不能永久设置呢? - Kokodoko
    @Kokodoko 你可以将该标志添加到 package.json 中的一个启动脚本中。 - jewbix.cube

    61
    你仍然可以在 Node.js 的 ES6 模块中导入 require
    import { createRequire } from "module"; // Bring in the ability to create the 'require' method
    const require = createRequire(import.meta.url); // construct the require method
    const my_json_file = require("path/to/json/your-json-file.json") // use the require method
    

    11
    Node.Js v15最新版本提示错误ReferenceError: require is not defined - C Alonso C Ortega
    7
    我们正在第二行创建require。如果未定义,那么您必须跳过了前几行。 - Carter Cobb

    28

    您可以像在node-js文档中一样使用它:

    import { readFile } from 'fs/promises';
    
    const json = JSON.parse(await readFile(new URL('../../package.json', import.meta.url)));
    

    2
    如果您正在服务器上执行此操作...我强烈推荐使用更干净的 fs-extra,它承诺一切透明,并支持递归目录复制。 - Ray Foss
    1
    eslint 抛出错误,因为 await 关键字只能在 async 函数内部使用。 - Sina

    20

    2022

    来自Node.js v16v18 官方文档:

    import SomeJson from './some.json' assert { type: 'json' }
    

    然后使用相应的实验性标志运行它:

    node --experimental-json-modules ./your-file.js
    

    -14

    2
    只有在使用 npm 启动应用程序时才能正常工作,但这并非总是如此。 - DarkLite1
    你尝试使用fs加载文件了吗? - Osama Abdullah
    这似乎是一种不好的做法,因为它会加载完整的文件,显示依赖项和其他信息,使应用程序容易受到攻击。 - DarkLite1
    由于提到的安全问题以及对Deno和Qbrt的支持不足,这个功能可能会被移除。 - Ray Foss

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