клиентское кэширование файлов

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

Обходное решение для этой проблемы должно переименовать все файлы (как часть сборки), такой, что имя файла включает хеш MD5, он - содержание, например.

foo.js -> foo_AS577688BC87654.js
me.png -> me_32126A88BC3456BB.png

Однако в дополнение к переименованию самих файлов, все ссылки на эти файлы должны быть изменены. Для экс-клена тег такой как <img src="me.png"/> должен быть изменен на <img src="me_32126A88BC3456BB.png"/>.

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

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

Существует ли лучшее решение?

Спасибо, Дон

16
задан Dónal 11 August 2010 в 14:17
поделиться

5 ответов

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

Вы можете сделать это следующим образом: добавьте правило перезаписи в вашу конфигурацию Apache, например:

RewriteRule ^(.+)\.(.+)\.(js|css|jpg|png|gif)$ $1.$3

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

Затем вместо записи:

<img src="image.png" />

Просто вызовите функцию PHP:

<img src="<?php versionFile('image.png'); ?>" />

С помощью versionFile(), выглядящей следующим образом:

function versionFile($file){
    $path = pathinfo($file);
    $ver = '.'.filemtime($_SERVER['DOCUMENT_ROOT'].$file).'.';
    echo $path['dirname'].'/'.str_replace('.', $ver, $path['basename']);
}

Вот и все! Браузер запросит image.123456789.png, Apache перенаправит его на image.png, поэтому вы всегда будете пользоваться кешем и не будете иметь устаревших проблем, при этом вам не придется беспокоиться об управлении версиями файлов. .

Вы можете увидеть подробное объяснение этой техники здесь: http://particletree.com/notebook/automatically-version-your-css-and-javascript-files/

16
ответ дан 30 November 2019 в 16:00
поделиться

Почему бы просто не добавить в строку запроса номер "версии" и не обновлять версию каждый раз?

foo.js -> foo.js?version=5

Во время сборки все равно придется немного поработать, чтобы обновить номера версий, но имена файлов не нужно менять.

9
ответ дан 30 November 2019 в 16:00
поделиться

Переименование ваших ресурсов - это правильный путь, хотя мы используем номер сборки и встраиваем его в имя файла вместо хеша MD5

foo.js -> foo.123.js

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

Затем мы используем настраиваемые элементы управления для создания ссылок на ресурсы при загрузке страницы на основе номера сборки, который хранится в настройках приложения.

6
ответ дан 30 November 2019 в 16:00
поделиться

Я также думал об этом для сайта, который я поддерживаю, где было бы большой работой изменить все ссылки. У меня есть две идеи:

1. Установите заголовки срока действия удаленного кэша и примените изменения, которые вы предлагаете для наиболее часто загружаемых файлов. Для других файлов установите заголовки, чтобы срок их действия истекал через очень короткое время, например. 10 минут. Затем, если у вас есть 10-минутный простой при обновлении приложения, кеши будут обновляться к тому времени, когда пользователи заходят на сайт. Общая навигация по сайту должна быть улучшена, так как файлы нужно будет загружать только каждые 10 минут, а не каждый клик.

2. Каждый раз, когда новая версия приложения развертывается в другом контексте, который содержит номер версии. например. www.site.com/app_2_6_0/ Я не совсем уверен в этом, так как закладки пользователей будут ломаться при каждом обновлении.

1
ответ дан 30 November 2019 в 16:00
поделиться

Мы следовали схеме, аналогичной PJP, используя Rails и Nginx.

Мы хотели, чтобы изображения пользовательских аватаров кешировались браузером, но при смене аватара нам нужно было сделать кеш недействительным как можно скорее.

Мы добавили в модель аватара метод добавления отметки времени к имени файла:

return "/images/#{sourcedir}/#{user.login}-#{self.updated_at.to_s(:flat_string)}.png"

Во всех местах кода, где использовались аватары, мы ссылались на этот метод, а не на URL. В конфигурацию Nginx мы добавили следующее переписывание:

rewrite "^/images/avatars/(.+)-[\d]{12}.png"    /images/avatars/$1.png;
rewrite "^/images/small-avatars/(.+)-[\d]{12}.png"      /images/small-avatars/$1.png;

Это означало, что если файл изменился, его URL-адрес в HTML изменился, поэтому браузер пользователя сделал новый запрос на файл. Когда запрос достиг Nginx, он был переписан в простое имя файла.

3
ответ дан 30 November 2019 в 16:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: