0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

next-intlは時代遅れなのか?見えてきたボトルネックと実践的な最適化手法

0
Posted at

next-intlは時代遅れなのか?見えてきたボトルネックと実践的な最適化手法

55e9a500-e8dc-4eda-956c-e250cc352b8e.jpeg

Next.jsがPages RouterからApp Routerへ移行し、組み込みのi18nルーティングが廃止された際、コミュニティの標準的な選択肢となったのが next-intl でした。メンテナーの対応も迅速で、多くのチームが多言語サイトの構築に採用してきたはずです。

私自身、多言語対応したNext.jsアプリのチューニングに長く携わってきました。ここ数年でReactエコシステム全体がServer Components(RSC)やコンパイラによる最適化へ大きく舵を切る中、next-intl を本番環境でプロファイリングしてみると、現在の設計に起因するいくつかのボトルネックが見えてきます。

一番の問題は、初期ランタイムの大きさ(クライアントプロバイダーとICUパーサーだけで、テキスト描画前にgzipで約12KB消費します)だけではありません。それ以上に深刻なのが「別ページの翻訳文言の漏洩」です。

大半のプロジェクトでは、公式ガイドに従ってルートレイアウトに NextIntlClientProvider を置き、getMessages() で辞書を一括注入しています。その結果、ユーザーがただのお問い合わせページ(/contact)を開いただけなのに、ダッシュボードや料金プラン、設定画面など、アプリ全体の全翻訳データをブラウザがダウンロードしてしまいます。標準的な10画面のアプリで検証したところ、1ページに届く翻訳データの実に9割近くが、そのページでは一切使われない別ルートのものでした。

さらに、t("key") は実行時に文字列を動的に解決する仕組みのため、WebpackやTurbopackなどのバンドラはどの文言が実際に使われているかを事前に判別できません。そのため、未使用の文言をツリーシェイキング(Tree-shaking)で削ることもできません。

Server Components(RSC)周りのDX摩擦も見逃せません。App Routerで静的レンダリング(SSG)を成立させるために、next-intl は setRequestLocale(locale)(旧 unstable_setRequestLocale)というボイラープレートを導入せざるを得ませんでした。すべてのレイアウト、サブルート、ページ冒頭でこれを愚直に呼び出さなければならず、1箇所でも忘れるとNext.jsは警告もなしに静的生成を諦め、リクエスト毎の動的レンダリングにフォールバックしてしまいます。また、共通のデザインシステムや独立したクライアントコンポーネント内では、翻訳を同期的に取得する綺麗な手段が存在せず、コンテキストプロバイダーで囲むか、階層ごとに locale をバケツリレー(prop-drilling)するしかありません。

では、この構成をどう最適化すべきか?

現在本番で next-intl を運用している場合、いくつか現実的なアプローチがあります。

まず手軽なのは、ルートレイアウトでの全件注入をやめることです。JSONファイルを画面ごとのネームスペースに分割し、各ページやサブルートのコンポーネント内で getMessages() を呼んで必要な文言だけを渡すようにします。ネームスペースのマッピングを手作業でメンテする手間は増えますが、他画面の不要な文言が混入するのを即座に軽減できます。

次に、可能な限りReact Server Components(RSC)へ処理を寄せることです。クライアントコンポーネントの useTranslations() ではなく、サーバーコンポーネント側の getTranslations() を使ってサーバー側でHTMLとしてレンダリングできれば、クライアントランタイムのオーバーヘッドもハイドレーションの負荷もゼロに抑えられます。

そしてもう一つの選択肢が、ビルド時の静的解析を取り入れることです。最近のi18nのアプローチは、生の巨大なJSON辞書をブラウザに丸ごと送るスタイルから離れつつあります。例えばIntlayerのような手法では、コンパイル時にコンポーネントのインポートを解析し、各ルートで実際に使われる文言だけを静的に抽出します。ネームスペースの手動管理はもちろん、setRequestLocale の記述やデザインシステムでのpropバケツリレーも不要になります。既存の大規模アプリであれば、@intlayer/next-intl のような互換パッケージを使って既存の useTranslations 呼び出しをそのまま活かしつつ、内部だけコンパイラ最適化に差し替えることも可能です。

もしNext.jsで多言語アプリを運用されているなら、一度ブラウザの開発者ツールで初期読み込み時にどれだけ不要な翻訳テキストが流れているか確認してみる価値はあると思います。

詳細なベンチマークデータや検証手法については、こちらの元記事にまとめています:
https://intlayer.org/blog/is-next-intl-outdated

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?