ryne

ryne

github

nuxt + useDark ダークモードのフラッシュ問題

問題#

毎回リフレッシュするたびに、ページがフラッシュします。例えば、黒色に設定されたものが初期状態で白色になり、再び黒色に戻る場合です。

原因#

useDark はデフォルトでローカルストレージに保存されますが、ssr 状態ではローカルストレージにアクセスできません。

処理#

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          innerHTML: `
            (function() {
              const isDark = localStorage.getItem('darkMode') === 'true' || 
                (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches);
              document.documentElement.classList.toggle('dark', isDark);
            })();
          `,
          type: 'text/javascript',
        },
      ],
    },
  },
})

続く問題#

Hydration class mismatch

原因#

フラッシュ問題は解決しましたが、useDark が ssr 時に初期化される値は依然として誤った値です(ローカルストレージにアクセスできません)。

解決#

セッションを使用して保存します。

const isDark = useDark({
    storageKey: 'vueuse-color-scheme',
    storage: {
      getItem(key: string) {
        if (import.meta.server) {
          // サーバー側はヘッダーからクッキーを取得します
          const cookieStr = useRequestHeaders(['cookie'])?.cookie || ''
          return cookieStr.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
        }
        return document.cookie.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
      },
      setItem(key: string, value: string) {
        document.cookie = `${key}=${value};path=/;max-age=${60 * 60 * 24 * 30}`
      },
    } as Storage,
  })
// nuxt.config.ts
script: [
        {
          innerHTML: `
            (function() {
              var getCookie = function(name) {
                return document.cookie.split('; ').find(row => row.startsWith(name))?.split('=')[1] || null;
              };
              var darkMode = getCookie('vueuse-color-scheme');
              if (darkMode === 'dark') {
                document.documentElement.classList.add('dark');
              } else {
                document.documentElement.classList.remove('dark');
              }
            })();
          `,
          type: 'text/javascript',
        },
      ],
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。