import导入JSON

7,886 阅读2分钟

导入断言

新的导入断言功能允许模块导入语句在模块说明符旁边包含附加信息。

该功能的最初用途是使 JSON 文档能够作为JSON 模块导入:

{ 'awesome' : 'man' }
import data from './awesome.json' assert { type : 'json' }

背景:JSON模块和MIME类型

一个自然要问的问题是为什么不能像这样自然而然的导入JSON模块

import json from './conf.json'

web平台在执行之前通常会检查模块资源的MIME类型的有效性,理论上改MIME类型也可以用于确定将资源视为JSONjavascript模块。

但是,仅依赖MIME类型存在安全问题

模块可以跨源导入,开发人员可以从第三方模块导入JSON文件

它们可能认为即使导入不信任的第三方模块,只要JSON得到适当的处理,这也是基本安全的,因为JSON不会执行脚本

但是第三方脚本实际上可以在这种情况下执行,因为第三方服务器可能会意外的返回JavaScript/MIME类型和恶意JavaScript负载,在导入的作用于中执行代码

//如果以evil.com为例

//JavaScript MIME类型(例如“text/JavaScript”)!

import data from 'https://evil.com/data.json';

文件拓展名不能用于确定模块类型,因为它们不是web内容类型的可靠标准

因此需要导入断言来指定预期的模块类型来预防这种权限提升陷阱

当开发人员想要导入JSON模块时,他们必须使用导入断言来制定文件类型为JSON,如果从网络得到的MIME类型与预期的MIME类型不匹配,则会导入失败

// 如果evil.com以非JSON MIME类型响应,则失败。
import data from 'https://evil.com/data.json' assert { type: 'json' };

动态Import()

断言也可以使用新的第二个参数传递给动态Import()

// foo.json
{ "answer": 42 }
// main.mjs
const jsonModule = await import('./foo.json', {
  assert: { type: 'json' }
});
console.log(jsonModule.default.answer); // 42

JSON 内容是模块的默认导出,因此通过default获取内容.

总结

目前导入断言的唯一用途上指定导入模块类型。

但是该功能旨在允许任意键/值对。因此如果以其它方式限制模块导入变得有用,将来可能会添加其他用途

同时,在 Chromium 91 中默认提供具有新导入断言语法的 JSON 模块。

css模块脚本也即将推出,使用相同的模块断言类型语法

引用:

github.com/tc39/propos…

developer.mozilla.org/zh-CN/docs/…

github.com/w3c/webcomp…

github.com/tc39/propos…

chromestatus.com/feature/594…

v8.dev/features/im…