JavaScript 中的 JSON Modules

2,435 阅读3分钟

本文为翻译

原文标题:JSON Modules in JavaScript

原文作者:Dmitri Pavlutin

原文地址:dmitripavlutin.com/javascript-…

ECMAScript 模块系统(importexport 关键字)默认只能引入 JavaScript 代码。

把应用程序的配置保存在 JSON 文件中能为我们带来很多便利,因此,你可能会想要直接在 ES module 中导入 JSON 文件。

CommonJS 模块 可已经支持 导入 JSON 很久了。

很幸运,一个名为 JSON modules 的新提案已经进入 stage 3 了,它是一种在 ES module 中 导入 JSON 的方式。我们来看看 JSON modules 是如何工作的吧。

1. 导入 config.json

我们先从一个 JSON 文件 config.json 开始,里面包含了一些 应用程序的配置项:应用名 和 当前版本。

{
  "name": "My Application",
  "version": "v1.2"
}

如何才能将 config.json 导入 ES module 呢?

举个例子,我们要创建一个简单的 web 应用程序,它会通过 JSON 配置文件 来 渲染 应用名 和 应用版本。

我们尝试直接导入 config.json ,这时 Node.js 会抛出一个错误:

import http from 'http';
import config from './config.json';
http
  .createServer((req, res) => {
    res.write(`App name: ${config.name}\n`);
    res.write(`App version: ${config.version}`);
    res.end();
  })
  .listen(8080);

启动应用程序的时候,Node.js 抛出错误 TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".json"

在 Node.js 中 使用 import 语句,默认会期望 引入的是 JavaScript 代码。不过幸亏有 JSON modules 提案,我们可以指定JSON 为 导入数据类型。

在修复这个应用程序的代码前,我们先简短介绍下 JSON modules 提案是什么。

2. JSON modules 提案

JSON modules 提案 的本质是:允许在 ES module 中使用常规的 import 语句 导入 JSON 数据。

我们可以通过增加 导入断言 来导入 JSON 内容:

import jsonContent from "./file.json" assert { type: "json" };

assert { type: "json" }导入断言(import assertion),它指定了模块应当被解析和导入的格式为 JSON。

jsonContent 变量中存储了 解析 file.json 文件后创建的 纯 JavaScript 对象。

JSON module 的导入 必须是 默认导入(default import)。不能使用 具名导入(named imports)。

JSON module 也可以动态导入:

const jsonContent = await import('./file.json', {
  assert: {
    type: 'json'
  }
});

在我们这些例子中,导入断言 都指定了 JSON 类型。但其实还有一个更具通用性的提案 import assertions (当前在 stage 3),该提案会允许我们导入更多数据格式,比如 CSS modules。

3. 启用 JSON modules

现在,我们把 JSON module 集成到 web 应用程序中:

import http from 'http';
import config from './config.json' assert { type: "json" };
http
  .createServer((req, res) => {
    res.write(`App name: ${config.name}\n`);
    res.write(`App version: ${config.version}`);
    res.end();
  })
  .listen(8080);

主模块现在可以导入 config.json 了,并访问到了 config.nameconfig.version

JSON modules 生效需要 17.1 及以上的 Node.js 版本,也可以通过携带 --experimental-json-modules 标志 来启用 试验性的 JSON modules

node --experimental-json-modules index.mjs

对于浏览器环境,从 Chrome 91 开始,可以使用 JSON modules。

4. 总结

默认情况下,ES module 只能导入 JavaScript 代码。

多亏了 JSON modules 提案,我们可以直接在 ES module 中导入 JSON 内容。只要在 import 语句后加入 导入断言 即可:

import jsonContent from "./file.json" assert { type: "json" };

可以在 17.1 及以上的 Node.js 版本 使用 JSON modules,也可以通过携带 试验性标志 --experimental-json-modules 或 在 Chrome 91 以上版本的浏览器 来使用它。