本文为翻译
原文标题:JSON Modules in JavaScript
原文作者:Dmitri Pavlutin
ECMAScript 模块系统(import 和 export 关键字)默认只能引入 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.name 和 config.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 以上版本的浏览器 来使用它。