新しいインポートアサーション機能により、モジュールインポート文にモジュール指定子の横に付加情報を追加できるようになりました。この機能の最初の用途は、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';
ウェブプラットフォームは、モジュールリソースを実行する前にそのMIMEタイプの有効性を確認します。理論的には、このMIMEタイプを使用して、リソースをJSONモジュールとして扱うか、JavaScriptモジュールとして扱うかを判断することもできます。
しかし、MIMEタイプだけに依存することにはセキュリティ上の問題があります。
モジュールはクロスオリジンでインポートでき、開発者はサードパーティソースからJSONモジュールをインポートする場合があります。JSONが適切にサニタイズされている限り、スクリプトを実行しないため、信頼できないサードパーティからのインポートでも基本的に安全であると考えるかもしれません。
しかし、サードパーティのスクリプトはこのシナリオで実際に実行される可能性があります。なぜなら、サードパーティのサーバーが予期せずJavaScript MIMEタイプと悪意のあるJavaScriptペイロードで応答し、インポーターのドメインでコードを実行できるからです。
// Executes JS if evil.com responds with a
// JavaScript MIME type (e.g. `text/javascript`)!
import data from 'https://evil.com/data.json';
ファイル拡張子は、モジュールタイプの決定に使用できません。なぜなら、それらはウェブ上ではコンテンツタイプの信頼できる指標ではないからです。そのため、代わりにインポートアサーションを使用して、期待されるモジュールタイプを示し、この権限の昇格の落とし穴を防ぎます。
開発者がJSONモジュールをインポートする場合、JSONであることを指定するためにインポートアサーションを使用する必要があります。ネットワークから受信したMIMEタイプが期待されるタイプと一致しない場合、インポートは失敗します。
// Fails if evil.com responds with a non-JSON MIME type.
import data from 'https://evil.com/data.json' assert { type: 'json' };
動的import()
#
インポートアサーションは、新しい2番目のパラメータを使用して動的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モジュールスクリプトも間もなく同じモジュールタイプアサーション構文を使用して提供されます。
インポートアサーションのサポート #
- Chrome: バージョン91以降でサポート
- Firefox: サポートなし
- Safari: サポートなし
- Node.js: サポートなし
- Babel: サポートあり