ES Modules での JSON インポート(Fetch 不要、バンドラー不要)
プレーンな ES モジュールプロジェクトで import config from './config.json' を試して壁にぶつかった経験があるなら、あなただけではありません。長年、バンドラーなしで JSON をインポートするには、fetch() に頼るか、データを JavaScript ファイルに変換する必要がありました。そうした回避策の時代は終わりました。
2025 年現在、import attributes はモダンブラウザ全体でベースラインとなっています。ビルドツールを一切必要とせず、ネイティブ JavaScript での JSON モジュールインポートが可能になりました。
重要なポイント
with { type: 'json' }を使用して、ES モジュールで JSON をネイティブにインポート可能 — バンドラーやfetch()は不要です。type属性はセキュリティ上必須です:ランタイムがファイルを処理する前に MIME タイプを検証することを保証します。- JSON モジュールは default export のみを公開します。インポート後に分割代入してください。
- JSON ファイルは、正しい
Content-Type: application/jsonヘッダーを付けて HTTP 経由で提供される必要があります。
モダンな構文:Import Attributes
現在の構文では、with キーワードを使用してモジュールタイプを宣言します:
// Static import
import config from './config.json' with { type: 'json' }
console.log(config.apiUrl)
動的読み込みの場合:
// Dynamic import
const { default: config } = await import('./config.json', {
with: { type: 'json' }
})
注意: 古い
assert { type: 'json' }構文(Chrome 91–122 でサポート)は現在非推奨です。常にwithを使用してください。
type: 'json' 属性が必須である理由
with { type: 'json' } 属性は単なる装飾ではありません。特定のセキュリティ目的を果たします:ブラウザまたはランタイムに対して、何かを処理する前にレスポンスの MIME タイプを application/json として検証することを強制します。
これがないと、サーバーが JSON ファイルを装った JavaScript を返す可能性があり、エンジンにはその区別を強制する方法がありません。type 属性はそれを防ぎます。
JSON モジュールは Default Export のみを持つ
開発者がつまずく点の一つ:JSON モジュールは名前付きエクスポートをサポートしていません。JSON オブジェクト全体が default export として提供されます。
import data from './data.json' with { type: 'json' }
// ✅ 正しい
const { users, settings } = data
// ❌ これは動作しません
import { users } from './data.json' with { type: 'json' }
インポート後に default export から分割代入してください。
Discover how at OpenReplay.com.
ブラウザと Node.js のサポート
| 環境 | 最小バージョン |
|---|---|
| Chrome | 123+ |
| Firefox | 138+ |
| Safari | 17.2+ |
| Node.js | 現行 LTS 以降 |
これらはすべて現在広く展開されています。モダンブラウザと現行の Node.js リリースをターゲットにしている場合、JSON を読み込むためにバンドラーや fetch() 呼び出しは必要ありません。
注意: 以前の Node.js バージョンでは、実験的フラグの背後で JSON モジュールが提供されていました。import attributes を使用した JSON モジュールサポートは、現在の Node.js リリースで安定しています。正確なバージョンの詳細については、Node.js ESM ドキュメントを参照してください。
本番環境に出す前に知っておくべき実用的な制約
HTTP サーバーが必要です。 JSON モジュールを含むモジュールインポートは、通常 file:// 経由でページを直接読み込む場合には動作しません。ブラウザはモジュール読み込みに厳格なセキュリティルールを適用します。Vite、serve、または任意の静的ファイルサーバーのようなローカル開発サーバーを使用してください。
JSON ファイルは正しい MIME タイプで提供される必要があります。 サーバーは Content-Type: application/json を返す必要があります。ほとんどの静的サーバーは .json ファイルに対してこれを自動的に処理しますが、カスタムサーバーや CDN 設定を使用している場合は再確認してください。
JSON は有効である必要があります。 インポートレベルでのエラー回復はありません。JSON ファイルの構文エラーは、モジュールの読み込みを完全に失敗させます。デプロイ前に JSON を検証してください。
実際の使用例
// config.json
{
"apiUrl": "https://api.example.com",
"timeout": 5000,
"features": {
"darkMode": true
}
}
// app.js
import config from './config.json' with { type: 'json' }
const { apiUrl, timeout, features } = config
if (!apiUrl || typeof timeout !== 'number') {
throw new Error('Invalid configuration')
}
このパターンは、設定ファイル、機能フラグ、i18n 文字列、またはアプリが起動時に必要とする任意の静的構造化データに対してクリーンに機能します。
まとめ
Import attributes により、fetch() なし、バンドラーなし、回避策なしで、ES モジュールで JSON をインポートするクリーンでネイティブな方法が提供されます。with { type: 'json' } 構文は、モダンブラウザと現行の Node.js リリースで広くサポートされています。ファイルが正しい MIME タイプで HTTP 経由で提供されていることを確認すれば、準備完了です。
よくある質問
はい。import attributes 提案は拡張可能に設計されています。たとえば、CSS モジュールスクリプトは、サポートされているブラウザで with { type: 'css' } を使用します。ただし、JSON は現在最も広くサポートされているタイプです。他のタイプはランタイムに依存し、まだどこでも利用できるわけではありません。
インポートは完全に失敗し、SyntaxError をスローします。生のレスポンスをキャッチして検査できる fetch とは異なり、JSON モジュールインポートは部分的な回復を提供しません。読み込み時のサイレント障害を避けるため、デプロイ前にリンターまたは CI チェックで JSON ファイルを検証してください。
JSON インポート自体には必要ありません。モダンブラウザと Node.js はネイティブに処理します。ただし、コード分割、ツリーシェイキング、古いターゲット向けの構文トランスパイルなど、他の理由でバンドラーが必要な場合があります。要点は、JSON 読み込み単独ではもはやバンドラーを必要としないということです。
ブラウザはモジュール読み込みに厳格なセキュリティルールを適用します。file プロトコルはモジュールリクエストに必要なメカニズムをサポートしていないため、ブラウザはインポートをブロックします。ローカルであっても、HTTP サーバー経由でファイルを提供する必要があります。Vite や serve npm パッケージなどのツールは、最小限のセットアップでこれを処理します。
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.