Я заметил, что некоторые браузеры (в частности, Firefox и Opera) очень усердно используют кэшированные копии файлов .css и .js даже между сеансами браузера. Это приводит к проблеме при обновлении одного из этих файлов, но браузер пользователя продолжает использовать кэшированную копию.
Вопрос в том, что является самым элегантным способом заставить браузер пользователя перезагрузить файл, когда он изменился?
В идеале решение не должно заставлять браузер перезагружать файл при каждом посещении страницы. Я опубликую свое собственное решение в качестве ответа, но мне любопытно, найдется ли у кого-нибудь лучшее решение, и я позволю вашим голосам решать.
Обновить :
После некоторого обсуждения здесь я нашел предложение Джона Милликина и da5id полезным. Оказывается, есть термин для этого: автоматическое управление версиями .
Ниже я разместил новый ответ, который представляет собой сочетание моего первоначального решения и предложения Джона.
Другая идея, предложенная SCdF , заключается в добавлении в файл фиктивной строки запроса. (Некоторый код Python для автоматического использования метки времени в качестве фиктивной строки запроса был представлен пи .). Тем не менее, существует некоторое обсуждение относительно того, будет ли браузер кэшировать файл со строкой запроса. (Помните, мы хотим, чтобы браузер кэшировал файл и использовал его при будущих посещениях. Мы хотим, чтобы он снова извлекал файл только после его изменения.)
Поскольку не ясно, что происходит с фиктивной строкой запроса, я не принимаю этот ответ.
ExpiresActive On ExpiresDefault "modification"
.iframe.contentWindow.location.reload(true)
. См. Метод (4) stackoverflow.com/a/22429796/999120 - это касается изображений, но то же самое относится.Ответы:
Обновление: переписано для включения предложений от Джона Милликина и da5id . Это решение написано на PHP, но должно быть легко адаптировано к другим языкам.
Обновление 2: Включение комментариев Ника Джонсона о том, что оригинальное
.htaccess
регулярное выражение может вызвать проблемы с такими файлами, какjson-1.3.js
. Решение состоит в том, чтобы переписать только если в конце есть ровно 10 цифр. (Поскольку 10 цифр охватывают все метки времени с 9.09.2001 по 20.11.22.)Сначала мы используем следующее правило перезаписи в .htaccess:
Теперь мы напишем следующую функцию PHP:
Теперь, куда бы вы ни включили свой CSS, измените его следующим образом:
К этому:
Таким образом, вам больше никогда не придется изменять тег ссылки, и пользователь всегда увидит последнюю версию CSS. Браузер сможет кэшировать файл CSS, но когда вы вносите какие-либо изменения в свой CSS, браузер увидит это как новый URL, поэтому он не будет использовать кэшированную копию.
Это также может работать с изображениями, значками и JavaScript. В основном все, что не генерируется динамически.
источник
file_exists
проверка действительно необходима?filemtime
вернет false в случае неудачи, так почему бы просто не присвоить значение filemtime переменной и проверить, является ли оно false перед переименованием файла? Это сократило бы одну ненужную файловую операцию, которая действительно сложилась бы.Простая клиентская техника
В общем, кеширование - это хорошо. Итак, есть несколько методов, в зависимости от того, решаете ли вы проблему самостоятельно при разработке веб-сайта или пытаетесь контролировать кеш в производственной среде.
Обычные посетители вашего сайта не будут иметь того опыта, который вы испытываете при разработке сайта. Так как среднестатистический посетитель посещает сайт реже (может быть, только несколько раз в месяц, если вы не являетесь сетью Google или hi5), тогда он с меньшей вероятностью будет хранить ваши файлы в кеше, и этого может быть достаточно. Если вы хотите принудительно ввести новую версию в браузер, вы всегда можете добавить строку запроса в запрос и увеличить номер версии при внесении серьезных изменений:
Это гарантирует, что каждый получит новый файл. Это работает, потому что браузер просматривает URL-адрес файла, чтобы определить, есть ли у него копия в кэше. Если ваш сервер не настроен на какие-либо действия со строкой запроса, он будет проигнорирован, но имя будет выглядеть как новый файл для браузера.
С другой стороны, если вы разрабатываете веб-сайт, вы не хотите менять номер версии каждый раз, когда сохраняете изменения в своей версии для разработки. Это было бы утомительно.
Поэтому, пока вы разрабатываете свой сайт, хорошим трюком будет автоматическая генерация параметра строки запроса:
Добавление строки запроса в запрос является хорошим способом создания версии ресурса, но для простого веб-сайта это может быть ненужным. И помните, кэширование - это хорошо.
Стоит также отметить, что браузер не скупится на хранение файлов в кеше. Браузеры имеют политики для такого рода вещей, и они обычно играют по правилам, изложенным в спецификации HTTP. Когда браузер делает запрос к серверу, часть ответа представляет собой заголовок EXPIRES ... дата, которая сообщает браузеру, как долго он должен храниться в кэше. В следующий раз, когда браузер встречает запрос на тот же файл, он видит, что у него есть копия в кеше, и смотрит на дату истечения срока действия, чтобы решить, следует ли его использовать.
Так что, хотите верьте, хотите нет, но на самом деле ваш сервер делает этот кеш браузера таким постоянным. Вы можете настроить параметры сервера и изменить заголовки EXPIRES, но небольшая техника, которую я написал выше, вероятно, намного проще для вас. Поскольку кэширование - это хорошо, обычно вы хотите установить эту дату далеко в будущее («Заголовок истекает в далеком будущем») и использовать метод, описанный выше, для принудительного изменения.
Если вам интересна дополнительная информация о HTTP или о том, как выполняются эти запросы, хорошая книга - «Высокопроизводительные веб-сайты» Стива Соудерса. Это очень хорошее введение в предмет.
источник
<link href='myCss.css?dev=14141'...>
Плагин mod_pagespeed от Google для apache сделает для вас автоматическое управление версиями. Это действительно хорошо.
Он анализирует HTML на выходе из веб-сервера (работает с PHP, rails, python, статическим HTML - чем угодно) и переписывает ссылки на CSS, JS, файлы изображений, чтобы они включали код id. Он обслуживает файлы по измененным URL-адресам с очень длинным контролем кэша. Когда файлы изменяются, он автоматически меняет URL-адреса, поэтому браузер должен повторно их получить. В основном это работает, без каких-либо изменений в вашем коде. Это даже уменьшит ваш код на выходе.
источник
Вместо того, чтобы менять версию вручную, я бы порекомендовал вам использовать хеш MD5 фактического файла CSS.
Таким образом, ваш URL будет что-то вроде
Вы все еще можете использовать правило перезаписи для удаления хэша, но преимущество заключается в том, что теперь вы можете установить политику кэширования на «кеширование навсегда», поскольку, если URL-адрес один и тот же, это означает, что файл не изменился.
Затем вы можете написать простой сценарий оболочки, который бы вычислял хеш файла и обновлял ваш тег (вы, вероятно, захотите переместить его в отдельный файл для включения).
Просто запускайте этот скрипт каждый раз, когда CSS меняется, и все хорошо. Браузер перезагрузит только ваши файлы, когда они будут изменены. Если вы сделаете правку, а затем отмените ее, вам не составит труда выяснить, к какой версии вам нужно вернуться, чтобы посетители не перезагружали ее.
источник
Не уверен, почему вы, ребята, так стараетесь реализовать это решение.
Все, что вам нужно сделать, если получить измененную временную метку файла и добавить ее в качестве строки запроса к файлу
В PHP я бы сделал это так:
filemtime - это функция PHP, которая возвращает метку времени изменения файла.
источник
mycss.css?1234567890
.<link rel="stylesheet" href="mycss.css?<?php echo filemtime('mycss.css') ?>"/>
, на случай, если некоторые аргументы в этой теме о кэшировании URL-адресов с помощью переменных GET (в предлагаемом формате) верны?ver=
так, кто знает!Вы можете просто поставить
?foo=1234
в конце вашего импорта CSS / JS, изменив 1234 на то, что вам нравится. Взгляните на SO HTML источник для примера.Идея там, что? параметры игнорируются / игнорируются по запросу в любом случае, и вы можете изменить это число при развертывании новой версии.
Примечание: есть некоторые аргументы относительно того, как именно это влияет на кэширование. Я считаю, что основная суть в том, что запросы GET с параметрами или без них должны быть кэшируемыми, поэтому вышеприведенное решение должно работать.
Тем не менее, и веб-сервер должен решить, хочет ли он придерживаться этой части спецификации, и браузер, который использует пользователь, поскольку он может просто пойти дальше и в любом случае запросить новую версию.
источник
Я слышал это называется "автоматическое управление версиями". Наиболее распространенный метод - включить mtime статического файла где-то в URL-адресе и удалить его с помощью обработчиков перезаписи или URL-адресов:
Смотрите также:
источник
30 или около того существующих ответов - отличный совет для веб-сайта около 2008 года. Однако, когда речь идет о современном одностраничном приложении (SPA), возможно, пришло время переосмыслить некоторые фундаментальные предположения ... в частности, идею о том, что веб-серверу желательно обслуживать только одну, самую последнюю версию файл.
Представьте, что вы - пользователь, у которого в браузере загружена версия M SPA:
/some.template
/some.template
- хотите ли вы вернуть версию M или N шаблона?Если формат
/some.template
изменился между версиями M и N (или файл был переименован или как-то еще), вы, вероятно, не хотите, чтобы версия N шаблона отправлялась в браузер, на котором запущена старая версия M анализатора . †Веб-приложения сталкиваются с этой проблемой, когда выполняются два условия:
Как только ваше приложение должно обслуживать несколько версий параллельно, решение проблемы кэширования и «перезагрузки» становится тривиальным:
/v<release_tag_1>/…files…
,/v<release_tag_2>/…files…
<script>
и<link>
теги и т.д. , чтобы указать на этот файл в одном из версионированных директорийЭтот последний шаг звучит сложно, так как он может потребовать вызова конструктора URL для каждого URL в коде на стороне сервера или на стороне клиента. Или вы можете просто использовать
<base>
тег и изменить текущую версию в одном месте.† Один из способов обойти это - заставить браузер перезагружать все, когда выходит новая версия. Но для того, чтобы позволить завершению любых выполняемых операций, все равно может быть проще поддерживать как минимум две версии параллельно: v-current и v-previous.
источник
base
тега! Что касается поддержки старого кода: это не всегда возможно и не всегда хорошая идея. Новые версии кода могут поддерживать критические изменения в других частях приложения или могут включать в себя экстренные исправления, исправления уязвимостей и так далее. Мне еще предстоит реализовать эту стратегию самостоятельно, но я всегда чувствовал, что общая архитектура должна позволять развертываниям помечать старую версиюobsolete
и принудительно перезагружать при следующем асинхронном вызове (или просто принудительно отключать все сеансы через WebSockets). ).Не используйте foo.css? Version = 1! Браузеры не должны кэшировать URL с помощью переменных GET. Согласно http://www.thinkvitamin.com/features/webapps/serving-javascript-fast , хотя IE и Firefox игнорируют это, Opera и Safari этого не делают! Вместо этого используйте foo.v1234.css и используйте правила перезаписи, чтобы удалить номер версии.
источник
В Laravel (PHP) мы можем сделать это следующим ясным и элегантным способом (используя метку времени изменения файла):
И похоже на CSS
Пример вывода html (
filemtime
время возврата в виде метки времени Unix )источник
RewriteRule нуждается в небольшом обновлении для файлов js или css, которые содержат точечную версионность в конце. Например, json-1.3.js.
Я добавил класс отрицания точки [^.] В регулярное выражение, так что .number. игнорируется
источник
^(.*)\.[\d]{10}\.(css|js)$ $1.$2
[^.]
здесь. Кроме того, нет смысла писать\d
внутри класса символов -\d+
будет делать то же самое. После публикации ваш шаблон будет соответствовать любому количеству символов (жадно), затем буквальной точке, затем не точке, затем одной или нескольким цифрам, затем точке, затемcss
илиjs
, затем концу имени файла. Нет совпадений для вашего примера ввода: regex101.com/r/RPGC62/1Для ASP.NET 4.5 и выше вы можете использовать связывание скриптов .
Есть и другие преимущества связывания, в том числе повышение производительности при первой загрузке страницы с минимизацией.
источник
Вот чистое решение JavaScript
Выше будет выглядеть последний раз, когда пользователь посетил ваш сайт. Если последний визит был до того, как вы выпустили новый код, он используется
location.reload(true)
для принудительного обновления страницы с сервера.Обычно я использую его как самый первый сценарий внутри,
<head>
поэтому он оценивается перед загрузкой любого другого содержимого. Если требуется перезагрузка, это вряд ли заметно для пользователя.Я использую локальное хранилище для хранения отметки времени последнего посещения в браузере, но вы можете добавить файлы cookie в список, если вы хотите поддерживать более старые версии IE.
источник
Интересный пост. Прочитав все ответы здесь, в сочетании с тем фактом, что у меня никогда не было проблем со «поддельными» строками запросов (что я не уверен, почему все так неохотно используют это), я думаю, что решение (которое устраняет необходимость в правилах переписывания apache как и в принятом ответе) - вычислить короткий HASH содержимого файла CSS (вместо файла datetime) в виде фиктивной строки запроса.
Это приведет к следующему:
Конечно, решения datetime также выполняют свою работу в случае редактирования файла CSS, но я думаю, что это касается содержимого файла css, а не файла datetime, так зачем смешивать их?
источник
Для моего развития я считаю, что хром имеет отличное решение.
https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload
Когда инструменты разработчика открыты, просто нажмите и удерживайте кнопку обновления и отпустите, когда вы наведете указатель мыши на «Очистить кэш и полная перезагрузка».
Это мой лучший друг, и это супер легкий способ получить то, что вы хотите!
источник
Спасибо Кипу за его идеальное решение!
Я расширил его, чтобы использовать его как Zend_view_Helper. Поскольку мой клиент запускал свою страницу на виртуальном хосте, я также расширил ее для этого.
Надеюсь, это поможет кому-то еще.
Приветствия и спасибо.
источник
Не нашли подход DOM на стороне клиента для динамического создания элемента узла сценария (или css):
источник
В Google Chrome есть « Жесткая перезагрузка», а также « Очистить кэш» и «Жесткая перезагрузка». Вы можете нажать и удерживать кнопку перезагрузки (в режиме проверки), чтобы выбрать ее.
источник
ant menu
>More Tools
>Developer Tools
акаright click
>Inspect Element
. Есть также настройка, скрытая где-то в инструментах разработчика (я забыл местоположение), чтобы перезагружать каждую перезагрузку.Вы можете принудительно использовать «кеширование всей сессии», если добавляете идентификатор сессии как простой параметр файла js / css:
Если вы хотите кэширование всей версии, вы можете добавить код для печати даты файла или аналогичный. Если вы используете Java, вы можете использовать пользовательский тег для создания ссылки элегантным способом.
источник
Скажем, у вас есть файл, доступный по адресу:
Вы можете добавить параметр запроса с информацией о версии в URI, например:
или вы можете добавить информацию о версии, например:
ИМХО, второй метод лучше подходит для CSS-файлов, потому что они могут ссылаться на изображения с использованием относительных URL, что означает, что если вы укажете
background-image
подобное, то так:его URL будет эффективно:
Это означает, что если вы обновите номер используемой версии, сервер будет рассматривать это как новый ресурс и не будет использовать кэшированную версию. Если вы основываете свой номер версии на Subversion / CVS / и т.д. пересмотр означает, что будут замечены изменения в изображениях, на которые есть ссылки в файлах CSS. Это не гарантируется первой схеме, то есть URL
images/happy.gif
относительно/styles/screen.css?v=1235
IS ,/styles/images/happy.gif
который не содержит никакой информации о версии.Я реализовал решение для кэширования, используя эту технику с сервлетами Java, и просто обрабатываю запросы
/v/*
с помощью сервлета, который делегирует базовый ресурс (т/styles/screen.css
. Е. ). В режиме разработки я установил кэширование заголовков , которые говорят клиенту всегда проверять свежесть ресурса с сервером (обычно это приводит к 304 , если вы делегировать для TomcatDefaultServlet
и.css
,.js
и т.д. файл не изменился) , а в режиме развертывания Я установил заголовки, которые говорят «кешировать навсегда».источник
<?php header( 'Location: folder1/login.phtml' ); ?>
.Вы можете просто добавить случайное число с помощью CSS / JS url, например
источник
Для ASP.NET я предполагаю следующее решение с расширенными настройками (режим отладки / выпуска, версии):
Файлы Js или Css включены таким образом:
Global.JsPostfix и Global.CssPostfix вычисляются в Global.asax следующим образом:
источник
Я недавно решил это с помощью Python. Вот код (должен быть легко адаптирован к другим языкам):
Этот код добавляет метку времени файлов в качестве параметра запроса к URL-адресу. Вызов следующей функции
приведет к
Преимущество, конечно, заключается в том, что вам больше никогда не придется менять html, прикосновение к файлу CSS автоматически вызовет аннулирование кэша. Работает очень хорошо и накладных расходов не заметно.
источник
Если вы используете git + PHP, вы можете перезагружать скрипт из кэша каждый раз, когда происходит изменение в git-репо, используя следующий код:
источник
Если вы разработчик и хотите избежать кеширования, на вкладке Chrome Network есть опция отключения кеша. В противном случае вы можете сделать это без инфраструктуры рендеринга сервера, используя два тега script.
источник
Этот вопрос очень старый, и он появляется первым делом, когда кто-нибудь гуглит эту проблему. Это не ответ на вопрос, как этого хочет операционная система, а ответ разработчикам с этой проблемой при разработке и тестировании. И я не могу опубликовать новый вопрос по этой теме, так как он будет помечен как дубликат.
Как и многие другие, я просто хотел кратко удалить кеширование.
"keep caching consistent with the file"
.. слишком много хлопот ..Вообще говоря, я не против загружать больше - даже загружать снова файлы, которые не изменились - в большинстве проектов - практически не имеет значения. При разработке приложения - мы в основном загружаем с диска,
localhost:port
так что - этаincrease in network traffic
проблема не является проблемой .Большинство небольших проектов просто играют - они никогда не попадают в производство. так что для них вам больше ничего не нужно ..
Таким образом, если вы используете Chrome Dev Tools , вы можете использовать этот метод отключения кэширования, как показано на рисунке ниже:
И если у вас есть проблемы с кэшированием Firefox :
Делайте это только в процессе разработки, вам также нужен механизм для принудительной перезагрузки для производства, так как ваши пользователи будут использовать старые недействительные модули кэша, если вы часто обновляете свое приложение и вы не предоставляете специальный механизм синхронизации кэша, подобный описанным в ответах. над.
Да, эта информация уже есть в предыдущих ответах, но мне все еще нужно было выполнить поиск в Google, чтобы найти ее.
Надеюсь, этот ответ очень ясен, и теперь вам не нужно.
источник
Кажется, что все ответы здесь предполагают какое-то управление версиями в схеме именования, которая имеет свои недостатки.
Браузеры должны хорошо знать, что кэшировать, а что нет, читая ответ веб-серверов, в частности, заголовки http - как долго этот ресурс действителен? был ли этот ресурс обновлен с тех пор, как я последний раз его получал? и так далее.
Если все настроено «правильно», простое обновление файлов вашего приложения должно (в какой-то момент) обновить кэши браузеров. Например, вы можете настроить свой веб-сервер так, чтобы браузер никогда не кэшировал файлы (что является плохой идеей).
Более подробное объяснение того, как это работает, можно найти здесь https://www.mnot.net/cache_docs/#WORK.
источник
Просто добавьте этот код, где вы хотите выполнить полную перезагрузку (заставить браузер перезагружать кэшированные файлы CSS / JS). Сделайте это внутри .load, чтобы он не обновлялся как цикл
источник
Просто используйте код на стороне сервера, чтобы добавить дату файла ... таким образом, он будет кэшироваться и перезагружаться только при изменении файла
В ASP.NET
Это может быть упрощено до:
Добавив метод расширения в свой проект, чтобы расширить страницу:
источник
Я предлагаю реализовать следующий процесс:
Версии ваших файлов CSS / JS при каждом развертывании, например: screen.1233.css (номер может быть вашей версией SVN, если вы используете систему управления версиями)
минимизируйте их, чтобы оптимизировать время загрузки
источник