Кэширование статики и cache-control

Thank you for reading this post, don't forget to subscribe!

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

Управ­ле­ние тем, какие фай­лы сле­ду­ет кэши­ро­вать осу­ществ­ля­ет­ся с помо­щью HTTP заго­лов­ков Cache-control и Expires. Сер­вер отправ­ля­ет такой заго­ло­вок вме­сте с отве­том, ука­зы­вая бра­у­зе­ру сто­ит или нет сохра­нить этот файл в локаль­ное хранилище.

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

Cache-control

Для того, что­бы управ­лять кэши­ро­ва­ни­ем в бра­у­зе­ре исполь­зу­ет­ся HTTP заго­ло­вок Cache-control. Его необ­хо­ди­мо пере­да­вать со все­ми фай­ла­ми, кото­рые нуж­но кэши­ро­вать. Он име­ет сле­ду­ю­щий формат:

  • private озна­ча­ет, кто кэши­ро­ва­ние будет рабо­тать толь­ко на бра­у­зе­ре поль­зо­ва­те­ля. Вме­сто это­го Вы може­те исполь­зо­вать инструк­цию public. Это раз­ре­ша­ет кэши­ро­ва­ние на пуб­лич­ных прок­си-сер­ве­рах (такие часто есть в компаниях).
  • no-cache озна­ча­ет, что дан­ный запрос нель­зя кэшировать.
  • max-age это вре­мя, на кото­рое будет зак­э­ши­ро­ван резуль­тат. Уста­нав­ли­ва­ет­ся в секундах.

Обыч­но это­го заго­лов­ка доста­точ­но для того, что­бы все заработало:

# зак­э­ши­ру­ет резуль­тат запро­са в бра­у­зе­ре на 60 секунд

# запре­тит кэши­ро­ва­ние запроса

Expires

Допол­ни­тель­ный заго­ло­вок HTTP Expires ука­зы­ва­ет дату и вре­мя, когда бра­у­зер дол­жен обно­вить кэш:

# Бра­у­зер отпра­вит повтор­ный запрос аж в 2037 году, до это­го вре­ме­ни он будет исполь­зо­вать кэш

Этот заго­ло­вок сле­ду­ет исполь­зо­вать вме­сте с Cache-Control.

Vary

Заго­ло­вок Vary поз­во­ля­ет уста­но­вить допол­ни­тель­ные пра­ви­ла для кэши­ро­ва­ния запросов:

# Бра­у­зер будет знать, что кон­тент может отли­чать­ся в зави­си­мо­сти от вер­сии сай­та (напри­мер, мобиль­ной и настольной)

Что кэшировать

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

  • Кар­тин­ки
  • CSS
  • Javascript
  • Загру­жа­е­мые фай­лы (архи­вы, доку­мен­ты и т.п.)

Использование в приложении

В при­ло­же­нии заго­лов­ки Cache-Control обыч­но не исполь­зу­ют­ся, т.к. при­ло­же­ния гене­ри­ру­ют дина­ми­че­ский кон­тент. Если же у Вас ред­ко изме­ня­ет­ся сай­та, Вы може­те доба­вить кэши­ро­ва­ние, что­бы сни­зить коли­че­ство запро­сов на сер­вер. Напри­мер, в PHP:

# Вклю­чим кэш на 1 час

Одна­ко луч­ше это­го не делать, т.к. при изме­не­нии кон­тен­та у раз­ных посе­ти­те­лей будут раз­ные вер­сии страниц.

Использование на Web сервере

Заго­лов­ки для кар­ти­нок и ста­ти­че­ских фай­лов (JS/CSS) нуж­но уста­нав­ли­вать на Web сервере.

Nginx

В Nginx кэши­ро­ва­ние вклю­ча­ет­ся инструк­ци­ей expires:

# Вклю­чит кэш на бес­ко­неч­ный срок для фай­лов с пере­чис­лен­ны­ми расширениями

Apache

В Apache кэши­ро­ва­ние вклю­ча­ет­ся моду­лем mod_expires и выгля­дит так:

# Вклю­ча­ет кэш для фай­лов на 1 месяц

Изменяемые файлов

Javascript и CSS фай­лы обыч­но изме­ня­ют­ся. Но зара­нее невоз­мож­но опре­де­лить когда нуж­но будет вне­сти изме­не­ние. Мож­но кэши­ро­вать такие фай­лы на корот­кое вре­мя (напри­мер мину­ту), но это не поз­во­лит исполь­зо­вать все пре­иму­ще­ства Cache-Control.

Бра­у­зер хра­нит в кэше фай­лы соот­вет­ствен­но их адре­сам URL. Если Мы доба­вим GET пара­метр в путь, путь изме­нит­ся и бра­у­зер зано­во запро­сит файл. Что нам и нуж­но. При каж­дом обнов­ле­нии CSS и Javascript фай­лов сле­ду­ет добав­лять в GET пара­метр новое значение:

Луч­ше все­го исполь­зо­вать после­до­ва­тель­ные чис­ла ( вер­сии), и при каж­дом изме­не­нии про­сто уве­ли­чи­вать их на единицу: