テーマの永続化とフラッシュの防止
テーマ設定をlocalStorageに保存し、Reactの読み込み前にテーマを設定するブロッキングスクリプトを挿入します
「テーマの永続化とフラッシュの防止」はCoddyKit上の無料React Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
誤ったテーマが一瞬表示される問題
ページの読み込み時、ReactがlocalStorageを読み取って正しいテーマを適用するには、JavaScriptのダウンロード、解析、実行が必要です。この間、ブラウザーはデフォルトのスタイルで描画します。ユーザーがダークモードを好み、デフォルトがライトテーマの場合、テーマが修正される前に短時間、白い画面が表示されます。
ブロッキングスクリプトによる解決策
この問題は、ほかのコードより先に同期的に実行されるインラインスクリプトをdocument headに配置することで解決できます。このスクリプトは直ちにlocalStorageを読み取り、document.documentElementにdata-themeを設定します。ブロッキングスクリプトなので、ブラウザーはコンテンツを描画する前にこの属性を適用できます。
ブロッキングが必要な理由
非同期スクリプトや遅延スクリプトは、HTMLの解析後、場合によっては初回描画後に実行されます。それでは目的を果たせません。ブロッキングインラインスクリプトにはasync属性やdefer属性を付けず、外部ファイルから読み込まないでください。パフォーマンスへの影響を抑えるため、スクリプトはごく小さくする必要があります。
インラインスクリプトの内容
ブロッキングスクリプトは最小限にします。localStorage.getItem('theme')を読み取り、フォールバックとしてwindow.matchMedia('(prefers-color-scheme: dark)').matchesを確認し、その後document.documentElement.setAttribute('data-theme', theme)を呼び出します。プライベートブラウジングなどでlocalStorageが利用できない場合に備え、try-catchで囲んでください。
Next.jsでの実装
Next.jsでは、next/scriptのScriptコンポーネントをstrategy="beforeInteractive"とともに_document.js内で使用します。beforeInteractive戦略により、ページのJavaScriptが実行される前にスクリプトがページHTMLへ挿入され、Next.jsのビルドパイプラインでも同じブロッキング動作を実現できます。
ViteとCRAでの実装
ViteまたはCreate React Appのプロジェクトでは、index.htmlを直接編集し、ほかのスクリプトより前にインラインスクリプトタグをhead内へ配置します。index.htmlがブラウザーのエントリーポイントなので、Reactが起動する前にスクリプトが実行されます。100バイト未満に収まるよう、簡潔に記述してください。
CookieまたはヘッダーによるSSRの解決策
サーバーレンダリングされたアプリでは、サーバーがリクエストとともに送信されたCookieからテーマを読み取れます。その後、サーバーはブラウザーへ送信する前に、レンダリング済みHTMLへdata-themeを設定します。最初のHTMLの1バイト目から正しいテーマが含まれるため、クライアント側での一瞬の表示崩れを完全に防げます。
一瞬の表示崩れを防ぐ完全な流れ
一連の流れは次のとおりです。ブラウザーがHTMLをダウンロードし、パーサーがブロッキングインラインスクリプトに遭遇し、スクリプトがlocalStorageを読み取ってdata-themeを設定し、パーサーが処理を続け、正しいテーマでページが描画され、ReactがハイドレーションしてlocalStorageから同じテーマを取得します。ユーザーは最初から一貫したテーマを目にできます。
表示崩れ防止のテスト
修正が機能することを確認するには、Chrome DevToolsを開いてNetworkタブへ移動し、通信速度をSlow 3Gに制限します。ページを再読み込みしてください。読み込み中にテーマが変わる場合は、表示崩れが解消されていません。ブロッキングスクリプトを配置すると、低速な接続でも初回描画から正しいテーマが表示されます。
ハイドレーション不一致のリスク
Reactの初期状態がライトテーマで、ハイドレーション前にブロッキングスクリプトがダークテーマを設定した場合、Reactがハイドレーションの不一致を警告することがあります。これを避けるには、初回レンダリング時にもlocalStorageを読み取ってReactのテーマ状態を初期化し、ReactがレンダリングしたHTMLとブロッキングスクリプトが設定したDOMの状態を一致させます。
Storybookとテスト環境での表示崩れ
Storybookとテスト環境ではindex.htmlが読み込まれないため、ブロッキングスクリプトは実行されません。これらの環境でデフォルトのdata-theme属性を適用するデコレーターまたはテストセットアップを用意してください。これにより、コンポーネントを分離して開発する際の紛らわしい見た目の不一致を防げます。
表示崩れ防止の手法
誤ったテーマが一瞬表示されるのを防ぐには、document headでどのような種類のスクリプトを使用する必要がありますか?
レッスンのまとめ: テーマの保持と表示崩れの防止
描画が行われる前にlocalStorageを読み取り、data-themeを設定する小さなブロッキングインラインスクリプトをドキュメントヘッドへ挿入して、誤ったテーマが一瞬表示されるのを防ぎます。Next.jsではstrategy="beforeInteractive"を使用し、Vite/CRAではindex.htmlへ直接追加します。SSRアプリではCookieを読み取ってサーバー側でテーマを設定できます。
よくある質問
「テーマの永続化とフラッシュの防止」レッスンは無料ですか?
はい。「テーマの永続化とフラッシュの防止」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「テーマの永続化とフラッシュの防止」で何を学びますか?
テーマ設定をlocalStorageに保存し、Reactの読み込み前にテーマを設定するブロッキングスクリプトを挿入します ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「テーマの永続化とフラッシュの防止」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- システムのカラースキームの検出
- テーマ切り替えのためのCSS変数
- テーマ状態のためのReact Context
- テーマの永続化とフラッシュの防止