React Academy · Урок

Сохранение темы и предотвращение мерцания

Сохраняйте предпочтение темы в localStorage и добавляйте блокирующий скрипт, устанавливающий тему до загрузки React

Урок 4 из 413 шагов

«Сохранение темы и предотвращение мерцания» — бесплатный урок React Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.

Проблема краткого отображения неправильной темы

При загрузке страницы React должен загрузить, разобрать и выполнить JavaScript, прежде чем сможет прочитать localStorage и применить правильную тему. В этот промежуток браузер отображает страницу с использованием стилей по умолчанию. Если пользователь предпочитает тёмную тему, а значение по умолчанию — светлое, он на короткое время видит белую вспышку, прежде чем тема исправится.

Решение с блокирующим скриптом

Решение заключается во встроенном скрипте, размещённом в document head, который синхронно выполняется до любого другого кода. Этот скрипт сразу читает localStorage и устанавливает data-theme в document.documentElement. Поскольку скрипт блокирует выполнение, браузер устанавливает атрибут до отрисовки содержимого.

Почему необходима блокировка

Асинхронные скрипты и скрипты с отложенным выполнением запускаются после разбора HTML и, возможно, после первой отрисовки. Это лишает решение смысла. Встроенный блокирующий скрипт не должен иметь атрибутов async или defer и не должен загружаться из внешнего файла. Скрипт должен быть очень небольшим, чтобы свести затраты производительности к минимуму.

Содержимое встроенного скрипта

Блокирующий скрипт должен быть минимальным: прочитайте localStorage.getItem('theme'), проверьте window.matchMedia('(prefers-color-scheme: dark)').matches как запасной вариант, а затем вызовите document.documentElement.setAttribute('data-theme', theme). Оберните его в обработчик исключений на случай, если localStorage недоступен в режиме приватного просмотра.

Реализация в Next.js

В Next.js используйте компонент Script из next/script со strategy="beforeInteractive" внутри _document.js. Стратегия beforeInteractive вставляет скрипт в HTML страницы до запуска любого JavaScript страницы, обеспечивая такое же блокирующее поведение в конвейере сборки Next.js.

Реализация в Vite и Create React App

В проекте на Vite или Create React App отредактируйте index.html напрямую и разместите встроенный тег скрипта в head перед всеми остальными скриптами. Поскольку index.html является точкой входа для браузера, скрипт выполняется до запуска React. Сделайте его кратким, чтобы уложиться в 100 байт.

Решение для SSR через cookie или заголовок

В приложении с серверной отрисовкой сервер может прочитать тему из cookie, отправленной вместе с запросом. Затем сервер устанавливает data-theme в сгенерированном HTML до отправки его браузеру. Это полностью устраняет вспышку на стороне клиента, поскольку правильная тема присутствует уже в самом первом байте HTML.

Полный процесс без вспышки

Полный процесс выглядит так: браузер загружает HTML, анализатор встречает встроенный блокирующий скрипт, скрипт читает localStorage и устанавливает data-theme, анализатор продолжает работу, страница отображается с правильной темой, React выполняет гидратацию и получает ту же тему из localStorage. Пользователь с самого начала видит одну и ту же тему.

Тестирование предотвращения вспышки

Чтобы проверить исправление, откройте Chrome DevTools, перейдите на вкладку «Сеть» и установите ограничение скорости «Медленный 3G». Перезагрузите страницу. Если во время загрузки тема меняется, вспышка не устранена. При наличии блокирующего скрипта первая отрисовка уже должна показывать правильную тему даже при медленном соединении.

Риск несоответствия при гидратации

Если начальное состояние React по умолчанию устанавливается в светлую тему, а блокирующий скрипт до гидратации установил тёмную, React может предупредить о несоответствии при гидратации. Чтобы избежать этого, при начальном отображении также инициализируйте состояние темы React чтением из localStorage. Тогда HTML, отображённый React, будет соответствовать состоянию DOM, установленному блокирующим скриптом.

Вспышка в Storybook и тестовых окружениях

Storybook и тестовые окружения не загружают ваш index.html, поэтому блокирующий скрипт не выполняется. Добавьте декоратор или настройку тестов, которая устанавливает атрибут data-theme по умолчанию в этих окружениях. Это предотвращает confusing визуальные несоответствия при изолированной разработке компонентов.

Метод предотвращения вспышки

Какой тип скрипта следует использовать в заголовке документа, чтобы предотвратить краткое отображение неправильной темы?

Итоги урока: сохранение темы и предотвращение вспышки

Предотвратите краткое отображение неправильной темы, добавив небольшой встроенный блокирующий скрипт в заголовок документа. Он должен прочитать localStorage и установить data-theme до первой отрисовки. В Next.js используйте strategy="beforeInteractive", а в Vite и Create React App добавьте скрипт непосредственно в index.html. Приложения SSR могут прочитать cookie и установить тему на стороне сервера.

Можно начать бесплатно

Изучай React с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
88
Уроки
324

Часто задаваемые вопросы

Урок «Сохранение темы и предотвращение мерцания» бесплатный?

Да — полный текст урока «Сохранение темы и предотвращение мерцания» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.

Чему я научусь в уроке «Сохранение темы и предотвращение мерцания»?

Сохраняйте предпочтение темы в localStorage и добавляйте блокирующий скрипт, устанавливающий тему до загрузки React Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать React Academy?

Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Сохранение темы и предотвращение мерцания»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке React Academy?

Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Определение системной цветовой схемы
  2. Переменные CSS для переключения темы
  3. React Context для состояния темы
  4. Сохранение темы и предотвращение мерцания
← Назад к React Academy