ECMAScript 提案:JSON modules

ECMAScript 提案:JSON modules

ECMAScript 模块系统(importexport 关键字)默认仅可以引用 JavaScript 代码。

但是一个实用的例子是存储应用的配置数据在 JSON 文件中,这样的话,我们想要在 ES 模块中直接引用 JSON 文件。

一直以来,commonjs 模块支持引用 JSON 文件格式。幸运的是,名为 JSON modules 的新提案处于 stage 3 状态,使得直接在 ES 模块中导入 JSON 文件成为可能。让我们看看 JSON 模块如何运行。

直接引用 JSON 文件

让我们尝试引用一个名为 config.json 的 JSON 文件,其中包含一个应用必须的配置信息:名称和当前版本。

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

如何在 ES 模块中引用 config.json

举例来说,让我们创建一个简单的 web 应用,从 JSON 配置文件中渲染出应用的名称和版本。

如果你尝试在 Node.js 中直接引用 config.json,将会抛出一个错误:

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 直接引用 JSON 文件的报错

Node.js 使用 import 声明的时候默认导入的是 JavaScript 代码。但是感谢 JSON modules 提案,现在你可以直接从 JSON 中引用数据。

在修复这个应用的错误之前,让我们通过一些章节来了解 JSON modules 提案是什么。

JSON modules 提案

JSON modules 提案的本质是允许在 ES 模块中通过标准的 import 声明引用 JSON 数据文件。JSON 内容通过 import 断言引用:

import jsonObject from './file.json' assert { type: 'json' };

assert { type: "json" } 是一个 import 断言标识模块应该作为 JSON 解析和引用。

jsonObject 变量包含解析 file.json 内容的 JavaScript 对象。

JSON 模块也可以动态导入:

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

当一个模块被动态引入,包括 JSON 模块,default content default 属性变为可用。

在上面的用例中 import 断言指定一个 JSON 类型。然而,这是一个更加通用的提案 import assertions 支持引入很多格式的数据,例如 CSS 模块。

允许 JSON modules 模块

现在,让我们结合 JSON 模块和上面的 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 的应用

JSON modules 支持运行的 Node.js 版本是 >=17.1,同时需要设置开启 --experimental-json-modules 标记 Experimental JSON modules

node --experimental-json-modules index.mjs

在浏览器环境中,Chrome 91 开始支持 JSON modules 模块。

总结

默认情况下,ES 模块仅支持导入 JavaScript 代码。

感谢 JSON modules 模块提案,使得可以直接在 ES 模块中直接导入 JSON 内容。仅需要在 import 声明的右侧使用 import 断言:

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

要开始使用 JSON modules 模块,需要 Node.js 17.1 版本并开启 --experimental-json-modules 标记,或者在 Chrome 91 及以上版本中。

本文作者 Dmitri Pavlutin,转载请注明来源链接:

原文链接:https://dmitripavlutin.com/javascript-json-modules/

本文链接:https://tie.pub/2021/12/json-modules/