Обожаю ваш тайник ❤️

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

Эта публикация является дополнением к видео «Любите свой кэш» , которое является частью расширенного контента на Chrome Dev Summit 2020. Обязательно посмотрите видео:

Когда пользователи загружают ваш сайт во второй раз, их браузер будет использовать ресурсы внутри своего HTTP-кэша, чтобы ускорить эту загрузку. Но стандарты кэширования в Интернете датируются 1999 годом, и они определены довольно широко — определение того, может ли файл, например CSS или изображение, быть повторно извлечен из сети, а не загружен из вашего кэша, является немного неточной наукой.

В этом посте я расскажу о разумном, современном значении по умолчанию для кэширования — таком, которое на самом деле вообще не кэширует . Но это всего лишь значение по умолчанию, и оно, конечно, более тонкое, чем просто «отключить его». Читайте дальше!

Цели

Когда сайт загружается во второй раз, у вас есть две цели:

  1. Убедитесь, что ваши пользователи получают самую последнюю доступную версию — если вы что-то изменили, это должно быть быстро отражено.
  2. Выполните пункт 1, извлекая из сети как можно меньше данных

В самом широком смысле, вы хотите отправлять только самые незначительные изменения вашим клиентам, когда они снова загружают ваш сайт. И структурирование вашего сайта для обеспечения наиболее эффективного распространения любых изменений является сложной задачей (подробнее об этом ниже и в видео).

Сказав это, у вас также есть другие ручки, когда вы рассматриваете кэширование — возможно, вы решили позволить HTTP-кешу браузера пользователя удерживать ваш сайт в течение длительного времени, чтобы для его обслуживания вообще не требовалось никаких сетевых запросов. Или вы создали service worker, который будет обслуживать сайт полностью в автономном режиме, прежде чем проверять, является ли он обновленным. Это экстремальный вариант, который является допустимым — и используется для многих веб-приложений, подобных офлайн-первым, — но веб не должен быть в экстремальном режиме только кэширования или даже полностью сетевого экстремального режима.

Фон

Как веб-разработчики, мы все привыкли к идее наличия «устаревшего кэша». Но мы почти инстинктивно знаем инструменты, которые помогут решить эту проблему: выполнить «жесткое обновление», или открыть окно в режиме инкогнито, или использовать некоторую комбинацию инструментов разработчика вашего браузера, чтобы очистить данные сайта.

Обычные пользователи в Интернете не имеют такой роскоши. Поэтому, хотя у нас есть некоторые основные цели — гарантировать, что наши пользователи отлично проведут время со своей второй загрузкой, также очень важно убедиться, что у них не будет плохого времени или они не застрянут. (Посмотрите видео, если хотите услышать, как я рассказываю о том, как мы чуть не застряли на сайте web.dev/live !)

Для справки, действительно распространенной причиной "устаревания кэша" на самом деле является кэширование по умолчанию 1999 года. Оно опирается на заголовок Last-Modified :

Диаграмма, показывающая, как долго различные ресурсы кэшируются браузером пользователя
Активы, созданные в разное время (серого цвета), будут кэшироваться для разного времени, поэтому вторая загрузка может получить комбинацию кэшированных и новых активов.

Каждый загруженный вами файл сохраняется еще на 10% от его текущего срока службы, как его видит ваш браузер. Например, если index.html был создан месяц назад, он будет кэшироваться вашим браузером еще около трех дней.

В свое время это была благая идея, но, учитывая тесно интегрированную природу современных веб-сайтов, такое поведение по умолчанию означает, что можно попасть в ситуацию, когда у пользователя будут файлы, предназначенные для разных версий вашего веб-сайта (например, JS из версии за вторник и CSS из версии за пятницу), и все потому, что эти файлы не были обновлены в одно и то же время.

Хорошо освещенная тропа

Современное значение по умолчанию для кэширования — это вообще не делать кэширования и использовать CDN , чтобы приблизить ваш контент к вашим пользователям. Каждый раз, когда пользователь загружает ваш сайт, он будет обращаться в сеть, чтобы проверить, актуален ли он. Этот запрос будет иметь низкую задержку, поскольку он будет предоставлен CDN, географически близкой к каждому конечному пользователю.

Вы можете настроить свой веб-хостинг для ответа на веб-запросы с помощью этого заголовка:

Cache-Control: max-age=0,must-revalidate,public

По сути, это означает, что файл действителен в течение какого-то времени, и вы должны подтвердить его в сети, прежде чем сможете использовать его снова (в противном случае он будет только «рекомендован»).

Этот процесс проверки относительно дешев с точки зрения переданных байтов — если большой файл изображения не изменился, ваш браузер получит небольшой ответ 304 — но он стоит задержки , поскольку пользователь все равно должен обратиться к сети, чтобы узнать. И это основной недостаток этого подхода. Он может работать очень хорошо для людей с быстрым соединением в первом мире, и где ваш CDN по выбору имеет большое покрытие, но не для тех людей, которые могут использовать более медленное мобильное соединение или плохую инфраструктуру.

Независимо от этого, это современный подход, который является стандартным для популярной CDN, Netlify , но может быть настроен практически для любой CDN. Для Firebase Hosting вы можете включить этот заголовок в раздел хостинга вашего файла firebase.json:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

Так что, хотя я все еще предлагаю это как разумное значение по умолчанию, это всего лишь значение по умолчанию! Читайте дальше, чтобы узнать, как вмешаться и обновить значения по умолчанию.

URL-адреса с отпечатками пальцев

Включая хэш содержимого файла в имя активов, изображений и т. д., обслуживаемых на вашем сайте, вы можете гарантировать, что эти файлы всегда будут иметь уникальное содержимое — это приведет к файлам с именами sitecode.af12de.js , например. Когда ваш сервер отвечает на запросы этих файлов, вы можете безопасно указать браузерам ваших конечных пользователей кэшировать их в течение длительного времени, настроив их с помощью этого заголовка:

Cache-Control: max-age=31536000,immutable

Это значение — год в секундах. И согласно спецификации, это фактически равно «вечно».

Важно, не генерируйте эти хэши вручную — это слишком много ручной работы! Вы можете использовать такие инструменты, как Webpack, Rollup и т. д., чтобы помочь вам в этом. Обязательно прочитайте о них больше на Tooling Report .

Помните, что не только JavaScript может извлечь выгоду из URL-адресов с отпечатками пальцев; таким образом можно именовать и такие ресурсы, как значки, CSS и другие неизменяемые файлы данных. (И обязательно посмотрите видео выше, чтобы узнать больше о разделении кода, которое позволяет вам отправлять меньше кода при каждом изменении вашего сайта.)

Независимо от того, как ваш сайт подходит к кэшированию, эти типы отпечатков пальцев невероятно ценны для любого сайта, который вы можете создать. Большинство сайтов просто не меняются с каждым релизом.

Конечно, мы не можем переименовать наши «дружелюбные», ориентированные на пользователя страницы таким образом: переименовав ваш файл index.html в index.abcd12.html — это невыполнимо, вы не можете сказать пользователям переходить на новый URL каждый раз, когда они загружают ваш сайт! Эти «дружелюбные» URL-адреса нельзя переименовать и кэшировать таким образом, что приводит меня к возможному компромиссу.

Золотая середина

Очевидно, что есть место для золотой середины, когда дело касается кэширования. Я представил два крайних варианта: кэшировать никогда или кэшировать навсегда . И будет ряд файлов, которые вы, возможно, захотите кэшировать на время, например, «дружественные» URL, о которых я упоминал выше.

Если вы хотите кэшировать эти "дружественные" URL и их HTML, стоит рассмотреть, какие зависимости они включают, как они могут кэшироваться и как кэширование их URL на время может повлиять на вас. Давайте рассмотрим HTML-страницу, которая включает изображение, подобное этому:

<img src="/images/foo.jpeg" loading="lazy" />

Если вы обновите или измените свой сайт, удалив или изменив это отложенно загружаемое изображение, пользователи, просматривающие кэшированную версию вашего HTML-кода, могут увидеть неправильное или отсутствующее изображение, поскольку при повторном посещении вашего сайта они все еще кэшируют исходный /images/foo.jpeg .

Если вы осторожны, это может вас не коснуться. Но в целом важно помнить, что ваш сайт — когда он кэшируется вашими конечными пользователями — больше не просто существует на ваших серверах. Скорее, он может существовать частями в кэшах браузеров ваших конечных пользователей.

В целом, большинство руководств по кэшированию будут говорить о таком типе настройки — хотите ли вы кэшировать на час, несколько часов и т. д. Чтобы настроить такой тип кэширования, используйте такой заголовок (который кэширует на 3600 секунд или один час):

Cache-Control: max-age=3600,immutable,public

И последнее. Если вы создаете своевременный контент, который обычно может быть доступен пользователям только один раз — например, новостные статьи! — я считаю, что их никогда не следует кэшировать, и вам следует использовать наше разумное значение по умолчанию выше. Я думаю, мы часто переоцениваем ценность кэширования по сравнению с желанием пользователя всегда видеть самый последний и лучший контент, например, критический обзор новостной статьи или текущего события.

Варианты, отличные от HTML

Помимо HTML, существуют и другие варианты файлов, которые занимают промежуточное положение:

  • В общем, ищите активы, которые не влияют на других.

    • Например: избегайте CSS, так как это приводит к изменениям в отображении HTML.
  • Большие изображения, которые используются как часть актуальных статей

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

    • Данные JSON о погоде могут публиковаться только каждый час, поэтому вы можете кэшировать предыдущий результат на час — он не изменится в вашем окне.
    • Сборки проектов с открытым исходным кодом могут быть ограничены по частоте, поэтому кэшируйте изображение статуса сборки до тех пор, пока не появится вероятность изменения статуса.

Краткое содержание

Когда пользователи загружают ваш сайт во второй раз, вы уже получили вотум доверия — они хотят вернуться и получить больше из того, что вы предлагаете. На этом этапе речь не всегда идет только о сокращении времени загрузки, и у вас есть множество доступных вам опций, чтобы гарантировать, что ваш браузер выполняет только ту работу, которая ему необходима для предоставления как быстрого, так и актуального опыта.

Кэширование — не новая концепция в Интернете, но, возможно, ему нужна разумная настройка по умолчанию — рассмотрите возможность ее использования и настоятельно подпишитесь на лучшие стратегии кэширования, когда они вам понадобятся. Спасибо за чтение!

Смотрите также

Общее руководство по HTTP-кешу см. в статье Предотвращение ненужных сетевых запросов с помощью HTTP-кеша .