ECMAScript 提案:JSON 模块

为什么我们要像模块一样导入 JSON?

很长一段时间以来,各种捆绑器(例如 webpack)允许我们像导入 ECMAScript 模块一样导入 JSON 数据。JSON 模块将其转化为标准功能。

为什么这么有趣?它提供了一种方便的使用方式,例如在我们的应用程序中使用配置数据。例如,以下文件结构:

my-app/
  src/
    config-data.json
    main.mjs

my-app/src/config-data.json 如下所示:

{
  "appName": "My App"
}

这是my-app/src/main.mjs

import configData from './config-data.json' assert {type: 'json'};
console.log(`I am ${configData.appName}!`);

assert到结束的语法称为导入断言。JSON 模块是创建导入断言的用例之一。

JSON 模块的默认导出包含 JSON 数据。没有命名的导出。

通过获取 JSON 数据fetch()

如果没有 JSON 模块,我们将不得不使用fetch()

async function fetchConfigData(relativePath) {
  const urlOfConfigData = new URL(
    relativePath, import.meta.url); // (A)
  const response = await fetch(urlOfConfigData.toString()); // (B)
  const json = await response.json(); // (C)
  return json;
}

const configData = await fetchConfigData('config-data.json');
console.log(`I am ${configData.appName}!`);

我们正在使用两个相对较新的功能:

  • Fetch API,一种基于 Promises 的API,用于下载 JavaScript 代码中的文件(B 行和 C 行)。
  • 模块元数据属性import.meta.url(A 行)。

fetch() 与 JSON 模块相比有两个缺点:

  • 代码稍微复杂一些。
  • Node.js 目前没有对fetch(). (而且我怀疑 JSON 模块将比fetch().更早得到支持。)

通过动态导入 JSON 模块import()

前面的import语句是静态的(在运行时固定)。我们还可以动态导入 JSON 模块(在运行时可更改):

async function importConfigData(moduleSpec) {
  const namespaceObj = await import(  // (A)
    moduleSpec, {assert: {type: 'json'}});
  return namespaceObj.default; // (B)
}

const configData = await importConfigData('./config-data.json');
console.log(`I am ${configData.appName}!`);

注意,所述import()操作者(A线)返回一个模块命名空间对象。这就是为什么我们.default在 B 行返回 property 的值(包含默认导出)。

为什么要额外的语法?

您可能想知道为什么我们必须在重要语句的末尾使用额外的语法:

import configData from './config-data.json' assert {type: 'json'};

为什么 JavaScript 不能通过查看文件扩展名来检测这是 JSON?

import configData from './config-data.json';

这是不可能的,因为它会导致安全问题:浏览器从不查看文件扩展名,他们查看内容类型。服务器负责为文件提供内容类型。因此,导入.json文件时可能会发生两件事:

  • 我们自己的服务器可能会发送其他内容类型,application/json并且导入会以某种方式出错。
  • 如果使用外部服务器,则风险更大:如果它发送内容类型为 的文件text/javascript,它可能会在我们的应用程序中执行代码。

因此,JavaScript 在导入 JSON 时不会依赖内容类型。

可用性

  • Chrome 91 支持 JSON 模块(来源:Chrome 平台状态)。
温馨提示 : 非特殊注明,否则均为©李联华的博客网原创文章,本站文章未经授权禁止任何形式转载;IP地址:18.117.156.170,归属地:俄亥俄州Dublin ,欢迎您的访问!
文章链接:https://www.lilianhua.com/ecmascript-proposal-json-module.html
Popup Image

通知

本站原则上是免费提供技术支持,但是服务器维护和运营成本高,可以实行自由赞助:赞助

Loading...