Как контролировать кэш CSS и скриптов

Браузер намертво кэширует стили и скрипты? Обновление стилий происходит только после нажатия клавиш Ctrl+f5? А при обычном обновлении страницы упорно продолжают подгружаться устаревшие css, скрипты и прочие файлы, который вы, будучи разработчиком уже поправили.

Такая ситуация не редка, и может весьма раздражать, заставляя буквально каждый раз вручную обновлять кэш, зижимая Ctrl+f5. Но неудобство на рабочем компьютере — пол беды. А реальные проблемы могут возникунуть:

  • При просмотре сайта заказчиком, которого не всегда можно научить "правильно перезагружить страницу"
  • При тестировании на мобильном устройстве, где скинуть кэш бывает совсем не просто

Решение проблемы кыширования CSS и скриптов

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

Эту задачу легко можно релизовать с помощью встроенной php-функции md5_file(), на вход она принемает путь к файлу, а выдает хэш. Ниже представлено простой скрипт, реализующий эту идею.

Именно таким образом интернет-гиганты обновляют дизайн у всех пользователей, не прося каждого нажать Ctrl+f5.

function fileCashFix($input){
  $file_path = $_SERVER['DOCUMENT_ROOT'].$input;
  if(file_exists($file_path)){
    return $input."?".md5_file($file_path);
  }else{
    return $input;
  }
}

После того как вы так или иначе применили этот подход вы можете:

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

Сниппет для MODx

  • Название сниппета: fileCashFix
  • Использование сниппета: <link href="[[!fileCashFix?input=`css/style.css`]]" rel="stylesheet">
$file_path = MODX_BASE_PATH.$input;
if(file_exists($file_path)){
  return $input."?".md5_file($file_path);
}else{
  return $input;
}

Для внешнего файла

! Запрос file_get_contents($input) может замедлять работу сайта, так как закачивает файл на сервер.

Использование сниппета: [[!fileCashFix?input=`https://fonts.googleapis.com/css?family=Roboto:400`]]. Важно указать именно https:// или https:// — просто // не пройдет.

$file_path = MODX_BASE_PATH.$input;
if(file_exists($file_path)){
  return $input."?".md5_file($file_path);
}else{
  // Если не нашли файл у себя, может быть передана ссылка на внешний файл
  $external_file = file_get_contents($input);
  if($external_file){
    // Проверяем, есть ли уже GET-параметры в запросе к файлу
    if(strpos($input, "?") !== false){
      return $input."&fileCashFix=".md5($external_file);
    }else{
      return $input."?fileCashFix=".md5($external_file);
    }
  }else{
    return $input;
  }
}

Комментарии (1)

  1. Дмитрий 26 января 2022, 00:28 # ↓ 0
    Здравствуйте!
    на Wordpress это как можно приспособить, куда кидать файл со сниппетом, в корень или добавлять код сниппета в файл function.php шаблона?
    *Комментарий будет опубликован после проверки модератором

    Комментарии easyComm

    Дмитрий 28 марта 2018, 14:51

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

    Администратор

    :)
    Ок, а как по-вашему он обрабатывает внешние ссылки? Ну вот просто логически поразмыслите... Можно ли обработать файл, не имея его у себя? Мы ведь не отправляем воркер на ТОТ сервер, как это бывает в работе с BigData. Мы просто скачиваем файл в какую-нибудь папку temp, работаем с ним и удаляем без следа. Это можно сравнить с работой браузера — браузер скачивает страницу сайта из интернета, чтобы отобразить ее для пользователя.
    ...А время дополнительное уходит потому что для скачивания файла нужно сделать все то же, что и браузеру - поиск DNS, ожидание ответа того сервера, время на загрузку, то-сё... И если это статичный маленький файл - хорошо, а если мы запрашиваем какой-нибудь условно XML на 150мб, генерируемый на лету, то задержка будет еще и из-за того, что файл долго генерировался где-то там на сервере. Все так же как и с открытием страницы в браузере.

    Дмитрий 28 марта 2018, 14:43

    А в чём смысл закачивать файл на сервак?

    Администратор

    А как еще его обработать функцией md5() или md5_file()?
    Он не сохраняется, но закачать-то его надо чтобы обработать.
    То же самое делает и предложенная Вами функция fopen()

    Дмитрий 28 марта 2018, 12:17

    Вот я сделал также для внешнего файла.
    <?php
    //
    $file_path = MODX_BASE_PATH.$input;
    if(file_exists($file_path)) { // Проверка файла на сервере
    return $input."?v=".md5_file($file_path);
    } else if (@fopen($input, "r")) { // Проверка доступа к внешней ссылке
    return $input."?v=".md5_file($input);
    } else {
    return $input;
    }

    Администратор

    Спасибо, добавил немного доработанный вариант реализации в статью.

    Дмитрий 28 марта 2018, 11:47

    Как сделать для внешнего файла?

    Good 17 марта 2018, 22:30

    очень интересно. но куда это нужно поместить? какой путь и в какой файл

    Павел 17 марта 2018, 22:30

    я так понял что на php5.3 и ниже, эта фича не работает?

    Похожие статьи

    pdoPage и getImageList - Постраничная навигация MIGX

    Генератор настроек MIGX

    Документация на русском по MODX MIGX

    Подсказки по работе и заготовки для MiniShop2

    Импорт и экспорт в MiniShop2. Реализация 1

    Как включить HTTPS (SSL) в MODX - Подробная инструкция

    Генерация YML для выгрузки в маркет

    Примеры работы с API MODX

    pThumb - ресайз изображений. Примеры использования.

    Примеры выборки where, optionFilters, innerJoin

    Расширение свойств товаров minishop2

    Добавить в письмо контактную информацию

    Пример перевода с помощью Yandex Translate API

    Сайт на обслуживании (выключить сайт)

    Примеры использования

    Вывести getImageList только если он не пустой

    Тип поля "Список ресурсов" (resourcelist) с ограничением по родителю (parents)

    Оформление и настройка easyComm. Комментарии и отзывы на сайте.

    Подсчет и вывод количества потомков ресурса в MODX

    Поиск на сайте с пакетом SimpleSearch

    Простая и симпатичная галерея fancybox

    Галерея. Вывести обложки альбомов и фотографии

    Вывод tv-параметров в формате -

    Универсальная форма обратной связи — feedBackForm

    Отредактировать письмо о заказе - добавить ТВ поле, или что-то еще

    Quip для MODX. Более рабочий вариант

    Сниппет для вывода размера и расширения файла

    pdoResources Заготовки для работы

    Простой аудио-плеер HTML5

    Вывести список всех опций MiniShop2

    Слайдер Slick slider в контенте ресурса

    Как поменять версию PHP, используемую в командной строке на Windows

    Как контролировать кэш CSS и скриптов

    Как поменять язык в Faker

    Сообщение о том, что сайт использует Cookie

    Изменить цену на товар в зависимости от количества при добавлении в корзину minishop2

    Подключить MODX в стороннем PHP файле

    Как создать ресурс процессором $modx->runProcessor('resource/create', $props)

    Простейшая авторизация

    Красивое адаптивное меню под pdoMenu

    Транслитерация URL в Laravel. Примеры str_slug()

    Массово обновить ТВ, или другое поле через базу

    Создать свою страницу в админке

    Изменить формат номера заказа

    Получить grandparent. Вывести родитель родителя

    Установить шаблон по-умолчанию для новых, создаваемых ресурсов

    Симпатичный список файлов, загружаемых к ресурсу через MIGX

    Вывести все доступные плейсхолдеры

    Простое логирование

    Отредактировать шаблон письма

    Общая сумма по каждому товару в корзине Minishop2

    Создать источник файлов

    Добавить скрипт перед тегом body

    Создать пакет с пользовательской таблицей

    Создать раздел с паролем на сайте MODX

    Что делать если ее приходит почта администратору

    Фильтрация по TV параметрам в msProducts

    FontAwesome - часто используемые иконки для шаблонов MODX

    Дата на русском

    Заготовки для автоматического заполнения товарами магазина 1.5.5.1.2

    getResources заготовки

    Загрузка сниппета после загрузки страницы через AjaxSnippet

    Обязательный чекбокс при оформлении заказа

    Курсы валют с cbr.ru на PHP

    Заготовки для работы

    Обработка остатков заказа в miniShop2

    Соответствие названия классов с названиями таблиц в MySQL

    Laravel Excel - Базовый экспорт

    Обновить alias (псевдоним) у всех ресурсов

    Разбить вывод pdoResources на несколько колонок (блоков)

    Баннеры с использованием BannerY

    Разные фишки, заготовки

    Получить вложенный массив из плоского

    Вывести время загрузки (формирования) страницы

    Бесплатная доставка от 5000 рублей в MiniShop2

    CSS для постраничной навигации pdoPage

    Счетчик посещений и скачиваний для сортировки ресурсов

    Расширить таблицу site_content (объект modResource) за 5 минут

    Вырезать кавычки — фильтр-сниппет MODX

    Динамическое поле emailSubject в FormIt

    Namespace на примерах - Как понять пространства имен в PHP

    Скрыть информацию о том, что сайт работает на MODX

    Как сделать middleware в Laravel 6 - простой пример

    Как обработать POST данные в PHP

    Отсортировать ресурсы по количеству комментариев Quip MODx

    Изменить цену на товар, если в корзине лежит товар из особой категории minishop2

    Cортировать по списку id в pdoResources и pdoTools

    Примеры работы с API

    Создать редирект через autoRedirector API

    Вывести 404 ошибку по настройке TV MODX

    Ответ для сервиса moneta.ru

    Как разместить исходный код сниппета на сайте, в документации

    Email сделать не обязательным полем

    Ускорить установку MODX revo до пары кликов

    Сделать все элементы статичными для Git и IDE

    Загрузить файл для постобработки

    Постраничная навигация — набор параметров и CSS PdoPage

    Не работает подгрузка товаров ajax mfilter2 на мобильном

    Сделать поле размер обязательным

    Получить время выполнения PHP скрипта. Решение в 3 строки кода

    Подключить текстовой редактор к доп. полям ресурса

    Настройка стилей для комментариев Tickets

    Динамическая замена шаблона ресурса - плагин

    Приветственный экран / заглушка на сайт

    Разместить корзину внутри блока с оформлением заказа

    Плагин для формирования замороженных URL с редиректом

    Кастомный чанк для AdminPanel

    Получить курсы валют с cbr.ru на PHP с кэшированием результатов

    Экспорт маршрутов из Laravel в JSON файл

    xPDO Выборка из одной таблицы с зацепкой значения из другой

    Вложенные условия в xPDO MODX

    Вывести список всех родителей в ТВ поле ресурса

    Кэширование в MODX: использование $modx->cacheManager

    Как получить данные пользователя сразу после авторизации через API

    Если getParentIds не работает в плагине

    Вывести список всех емэйлов miniShop2

    Контролировать кэширование файлов CSS и JS MiniShop2

    Не приходят / не отправляются письма - в чем причина?

    Фиксированная сортировка массива на основе хэша

    Вывести список всех файлов на сервере (и размер файла)

    Наш сайт использует куки, нажмите «ОК» если вы не против
    OK