你以为 fetch() 已经是导入 JSON 的最优解了?今天 import with 证明了这件事根本不是那么回事
你写了一个配置文件 data.json,想在浏览器里直接用。以前的做法:
老路子:先请求,再解析
fetch(./data.json).then(response => response.json()).then(data => console.log(data));
如果项目用了 Vite/Webpack,还有一个更简洁的方式——让构建工具在打包时直接把你要 import 的 JSON 嵌进 JS 文件里:
打包工具帮你做的事
import jsonData from ./data.json; // 构建时替换成内联对象
但这里有个问题:构建工具帮你变魔术,浏览器本身根本不支持直接 import JSON 模块。你以为你在 import 一个 JSON,其实打包工具偷偷把它编译成了一个巨大的 JS 对象塞进代码里。
这个问题,今天被 Import Attributes 从根本上变了。
import with type:json 是 TC39 ES2025 标准的一部分,Chrome 123+、Safari 17.2+、Node.js 20.10+ 已经全部支持。现在你可以直接在浏览器里 import JSON:
直接导入,浏览器原生支持
import data from ./data.json with { type: json };
console.log(data); // 就是一个普通 JS 对象
动态 import 也可以:
const data = await import(./data.json, { with: { type: json } });
console.log(data.default);
不光是 JSON,CSS 也可以。
import styles from ./button.css with { type: css };
document.adoptedStyleSheets = [styles];
这意味着某些场景下,你甚至可以不需要构建工具处理 CSS 模块了。
但这个 feature 真正厉害的地方,是安全层面。
之前有一个被低估的漏洞:你用 fetch() 去拿一个 JSON,服务器返回的 Content-Type 如果被劫持,变成了 text/javascript,浏览器会直接执行它——你的数据文件变成了代码执行入口。
Import Attributes 把这件事堵死了。with { type: json } 不只是声明我期望这是个 JSON,它还会让浏览器发出正确的 HTTP 请求头(Accept: application/json)和 Sec-Fetch-Dest 元数据头,服务器必须返回正确的 MIME 类型才能通过浏览器的安全校验。如果类型不匹配,import 直接失败,而不是悄悄执行恶意代码。
三步迁移方案:
第一步,确认环境支持。Chrome 123+、Safari 17.2+、Node.js 20.10+ 直接用;Firefox 暂无支持,需要 feature detection。
第二步,把现有的 fetch().then(r => r.json()) 改成 import 语句。如果 JSON 是静态的,直接替换。
第三步,删掉原来处理 JSON 内联的构建配置,减少打包体积。
一个关键提醒:
原来用 assert 关键字的写法已经在 V8 v12.3 废弃,v12.6 会完全移除。赶紧换成 with。
总结一下:
Import Attributes 解决的不只是少写两行代码,而是三件事:原生 JSON/CSS 模块导入(不需要构建工具代理)、正确的 CSP 和 MIME 类型校验(安全加固)、正确的 HTTP 请求头。对于还在用 fetch() + .json() 的项目,这是值得立刻迁移的 ES2025 特性——迁移成本极低,收益明确。
下一步动作:检查你的项目里有多少 fetch().then(r => r.json()) 调用,把静态配置类的改成 import with,把动态的保留 fetch 但加上类型校验。
评论区
登录后可评论。