Back

ES Modules での JSON インポート(Fetch 不要、バンドラー不要)

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 から分割代入してください。

ブラウザと Node.js のサポート

環境最小バージョン
Chrome123+
Firefox138+
Safari17.2+
Node.js現行 LTS 以降

これらはすべて現在広く展開されています。モダンブラウザと現行の Node.js リリースをターゲットにしている場合、JSON を読み込むためにバンドラーや fetch() 呼び出しは必要ありません。

注意: 以前の Node.js バージョンでは、実験的フラグの背後で JSON モジュールが提供されていました。import attributes を使用した JSON モジュールサポートは、現在の Node.js リリースで安定しています。正確なバージョンの詳細については、Node.js ESM ドキュメントを参照してください。

本番環境に出す前に知っておくべき実用的な制約

HTTP サーバーが必要です。 JSON モジュールを含むモジュールインポートは、通常 file:// 経由でページを直接読み込む場合には動作しません。ブラウザはモジュール読み込みに厳格なセキュリティルールを適用します。Viteserve、または任意の静的ファイルサーバーのようなローカル開発サーバーを使用してください。

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.

OpenReplay