ベンチマークと性能
本ベンチマークは、paraglide-js benchmark の測定手法をベースに、事前レンダリングとクライアント側のハイドレーションを伴う現代的な多言語 Web アプリにおいて、ユーザー端末が実際にダウンロードする全 i18n リソース(HTML + ランタイムコード + 辞書チャンク)の総ネットワーク転送サイズを測定したものです。
測定シナリオについて:クライアント JS を含まない純粋な静的ページ(Zero-JS MPA)では、サーバーが翻訳済み HTML を直接返すためクライアント側の i18n 負荷はゼロです。本ベンチマークは、クライアント側のハイドレーション、動的インタラクション(フォーム検証や動的メッセージ等)、およびクライアントサイドルーティングを伴う現代的なフルスタックアプリをシミュレートし、初回表示から操作可能状態に至るまでに必要な静的リソースの総サイズを測定しています。
評価対象と構成:
ts-intl(軽量ランタイム):default(全言語一括バンドル)およびlocale-splitting(言語単位の動的分割)の 2 構成。paraglide(コンパイラ方式):default(全言語コンパイル関数の一括バンドル)およびexperimental-middleware-locale-splitting(ルーティング連動分割)の 2 構成。i18next(従来型ランタイム):default(全言語 JSON の一括埋め込み)およびhttp-backend(クライアント側非同期 fetch)の 2 構成。
転送サイズの比較チャート
以下のデータは、Playwright ヘッドレス Chromium による実測 HTTP レスポンスサイズ(Transfer Size)に基づいています:
ネットワーク転送サイズ (KB)
Playwright Headless Chromium · Real HTTP Transfer Size
paraglideミドルウェア分割
-91%36.3 KB
ts-intlロケール分割
-86%57.8 KB
paraglideデフォルト一括
-82%76.6 KB
i18nextHTTP 動的取得
-55%188.7 KB
ts-intlデフォルト一括
-14%360.0 KB
i18nextデフォルト一括
Baseline420.4 KB
測定データ一覧
ワークロード基準:ページ上に 100 件のメッセージを描画(20% は動的変数補間を含む)。
シナリオ 1: 多言語スケール構成 (10 言語 · 辞書 500 項目)
辞書全体に 500 項目が含まれ、ページでそのうち 100 項目を参照・描画する場合:
| ライブラリと構成 | 転送サイズ | vs. i18next デフォルト | 特徴とメカニズム |
|---|---|---|---|
| paraglide (ミドルウェア分割) | 36.3 KB | -91.4% | JS 関数へコンパイル;Tree-shaking により未使用キーを削除;単一言語のみ転送 |
| ts-intl (ロケール分割) | 57.8 KB | -86.2% | コア約 2 KB;現在言語の 500 項目 JSON のみ転送 |
| paraglide (デフォルト一括) | 76.6 KB | -81.8% | Tree-shaking で未使用キーを削除;10 言語分のコンパイル関数を一括バンドル |
| i18next (HTTP 動的取得) | 188.7 KB | -55.1% | 現在言語の JSON を非同期取得;i18next 基本ランタイムを含む |
| ts-intl (デフォルト一括) | 360.0 KB | -14.4% | 10 言語分(計 500 項目)の JSON を一括バンドル |
| i18next (デフォルト一括) | 420.4 KB | 基準値 (Baseline) | 10 言語分の JSON と i18next フルランタイムを一括バンドル |
シナリオ 2: 初期プロジェクト構成 (5 言語 · 辞書 100 項目)
辞書全体に 100 項目が含まれ、その 100 項目すべてを描画する場合:
| ライブラリと構成 | 転送サイズ | vs. i18next デフォルト | 特徴とメカニズム |
|---|---|---|---|
| ts-intl (ロケール分割) | 29.7 KB | -83.8% | コア約 2 KB;現在言語の 100 項目 JSON のみ転送 |
| paraglide (ミドルウェア分割) | 36.1 KB | -80.3% | 現在言語の 100 件のコンパイル関数のみ転送 |
| paraglide (デフォルト一括) | 47.1 KB | -74.3% | 5 言語分(100 項目)のコンパイル関数を一括バンドル |
| ts-intl (デフォルト一括) | 56.9 KB | -69.0% | 5 言語分(100 項目)の JSON を一括バンドル |
| i18next (HTTP 動的取得) | 167.5 KB | -8.6% | 現在言語の JSON を非同期取得;i18next 基本ランタイムを含む |
| i18next (デフォルト一括) | 183.3 KB | 基準値 (Baseline) | 5 言語分の JSON と i18next フルランタイムを一括バンドル |
アーキテクチャと転送サイズの要因分析
1. コンパイラ方式における Tree-shaking の利点とトレードオフ
- 利点:
paraglideは各メッセージを独立した JavaScript 関数としてコンパイルします。バンドラー(Rollup / esbuild)は AST 解析により参照されていない関数を削除(Tree-shaking)できます。シナリオ 1 では、使用されていない 400 項目が除外されるため、最も小さい転送サイズ(36.3 KB)となります。 - トレードオフ:事前のコード生成ステップが必要であり、動的な外部 JSON 辞書の読み込みには適していません。
2. 軽量ランタイム方式における動的分割の利点
- コード生成が不要:
ts-intlは純粋な TypeScript ランタイムライブラリであり、事前の生成ステップなしに TypeScript オブジェクトまたは JSON 辞書を直接利用できます。 - 言語数増加に伴う転送サイズのフラット化:
locale-splittingモードでは、動的import()により各言語が個別チャンクに分割されます。閲覧中の言語チャンクのみが取得されるため、言語数が 5 から 10 以上に増加しても、単一ページの初期転送サイズはほぼ一定(約 30 KB 〜 57 KB)を保ちます。 - 最小限のランタイムサイズ:
ts-intlのコアは最小化後で約 2 KB です。数値、日付、複数形のフォーマットにはブラウザ標準の WebIntlAPI を直接利用するため、外部依存を含みません。
3. 従来型ランタイムのサイズ要因
i18nextは柔軟な設定機構、イベント機構、AST パーサーを備えているため、基本ランタイムの占有サイズが大きくなります。- 一般的な設定では全言語の辞書が単一エントリポイントに静的インポートされることが多く、使用の有無に関わらず全データが初回バンドルに含まれます。
ローカル環境での再現手順
リポジトリ内の apps/benchmark パッケージにて測定を再現できます:
# 1. Chromium シェルのインストール(初回のみ)
pnpm --filter @aaakul/ts-intl-benchmark prebench
# 2. 全ベンチマークの実行(SSG ビルドおよび Playwright 転送測定)
pnpm --filter @aaakul/ts-intl-benchmark bench
# 3. プレビューサーバーの起動 (http://localhost:3005 で閲覧)
pnpm --filter @aaakul/ts-intl-benchmark preview