Как заставить браузер перезагружать кэшированные файлы CSS/JS?

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

Вопрос заключается в следующем: каков самый элегантный способ заставить браузер пользователя перезагрузить файл после его изменения?

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

Обновить:

После некоторого обсуждения здесь я нашел предложение Джона Милликина и da5id полезным. Оказывается, есть термин для этого: автоматическое управление версиями.

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

Другая идея, предложенная SCdF, заключается в добавлении в файл фиктивной строки запроса. (Некоторый код Python для автоматического использования метки времени в качестве фиктивной строки запроса был представлен пи.). Тем не менее, существует некоторое обсуждение относительно того, будет ли браузер кэшировать файл со строкой запроса. (Помните, мы хотим, чтобы браузер кэшировал файл и использовал его при будущих посещениях. Мы хотим, чтобы он снова извлекал файл только после его изменения.)

Поскольку не ясно, что происходит с фиктивной строкой запроса, я не принимаю этот ответ.

58 ответов

Обновление: переписано с учетом предложений от Джона Милликина и da5id. Это решение написано на PHP, но должно быть легко адаптировано к другим языкам.

Обновление 2: включение комментариев от Ника Джонсона, что оригинал .htaccess регулярное выражение может вызвать проблемы с файлами, такими как json-1.3.js, Решение состоит в том, чтобы переписать только если в конце есть ровно 10 цифр. (Потому что 10 цифр охватывают все метки времени с 9.09.2001 по 20.11.22.)

Сначала мы используем следующее правило перезаписи в.htaccess:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

Теперь мы напишем следующую функцию PHP:

/**
 *  Given a file, i.e. /css/base.css, replaces it with a string containing the
 *  file's mtime, i.e. /css/base.1221534296.css.
 *  
 *  @param $file  The file to be loaded.  Must be an absolute path (i.e.
 *                starting with slash).
 */
function auto_version($file)
{
  if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;

  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

Теперь, куда бы вы ни включили свой CSS, измените его следующим образом:

<link rel="stylesheet" href="/css/base.css" type="text/css" />

К этому:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

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

Это также может работать с изображениями, значками и JavaScript. В основном все, что не генерируется динамически.

Простая клиентская техника

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

Обычные посетители вашего сайта не будут иметь того опыта, который вы испытываете при разработке сайта. Поскольку среднестатистический посетитель посещает сайт реже (может быть, только несколько раз в месяц, если вы не являетесь сетью Google или hi5), у них меньше шансов хранить ваши файлы в кеше, и этого может быть достаточно. Если вы хотите принудительно ввести новую версию в браузер, вы всегда можете добавить строку запроса к запросу и увеличить номер версии при внесении серьезных изменений:

<script src="/myJavascript.js?version=4"></script>

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

С другой стороны, если вы разрабатываете веб-сайт, вы не хотите менять номер версии каждый раз, когда сохраняете изменения в своей версии для разработки. Это было бы утомительно.

Поэтому, пока вы разрабатываете свой сайт, хорошим трюком будет автоматическая генерация параметра строки запроса:

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

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

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

Так что, хотите верьте, хотите нет, но на самом деле ваш сервер делает этот кеш браузера таким постоянным. Вы можете настроить параметры сервера и изменить заголовки EXPIRES, но небольшая техника, которую я написал выше, вероятно, намного проще для вас. Поскольку кэширование - это хорошо, обычно вы хотите установить эту дату далеко в будущее ("Заголовок истекающего далекого будущего") и использовать метод, описанный выше, для принудительного изменения.

Если вам интересна дополнительная информация о HTTP или о том, как выполняются эти запросы, хорошая книга - "Высокопроизводительные веб-сайты" Стива Соудерса. Это очень хорошее введение в предмет.

Плагин mod_pagespeed от Google для apache сделает для вас автоматическое управление версиями. Это действительно хорошо.

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

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

Все, что вам нужно сделать, если получить измененную временную метку файла и добавить ее в качестве строки запроса к файлу

В PHP я бы сделал это так:

<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">

filemtime - это функция PHP, которая возвращает измененную временную метку файла.

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

Таким образом, ваш URL будет что-то вроде

http://mysite.com/css/[md5_hash_here]/style.css

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

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

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

Вы можете просто поставить ?foo=1234 в конце импорта css / js измените значение 1234 на то, что вам нравится. Взгляните на источник SO html для примера.

Идея там, что? параметры игнорируются / игнорируются по запросу в любом случае, и вы можете изменить это число при развертывании новой версии.


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

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

Я слышал это называется "автоматическое управление версиями". Самый распространенный метод - включить mtime статического файла где-то в URL-адресе и удалить его с помощью обработчиков перезаписи или URL-адресов:

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

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

Представьте, что вы - пользователь, у которого в браузере загружена версия M SPA:

  1. Ваш конвейер CD развертывает новую версию N приложения на сервере
  2. Вы перемещаетесь внутри SPA, который отправляет XHR на сервер, чтобы получить /some.template
    • (Ваш браузер не обновил страницу, поэтому вы все еще используете версию M)
  3. Сервер отвечает содержимым /some.template - хотите ли вы вернуть версию M или N шаблона?

Если формат /some.template между версиями M и N (или файл был переименован или что-то еще) вы, вероятно, не хотите, чтобы версия N шаблона отправлялась в браузер, на котором запущена старая версия парсера M.

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

  • Ресурсы запрашиваются асинхронно через некоторое время после начальной загрузки страницы
  • Логика приложения предполагает вещи (которые могут измениться в будущих версиях) о содержимом ресурса

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

  1. Установите все файлы сайта в версионные каталоги: /v<release_tag_1>/…files…, /v<release_tag_2>/…files…
  2. Установите заголовки HTTP, чтобы позволить браузерам кэшировать файлы навсегда
    • (Или еще лучше, поместите все в CDN)
  3. Обновить все <script> а также <link> теги и т. д. для указания на этот файл в одном из версионных каталогов

Этот последний шаг звучит сложно, так как он может потребовать вызова конструктора URL для каждого URL в коде на стороне сервера или на стороне клиента. Или вы могли бы просто умно использовать <base> пометить и изменить текущую версию в одном месте.

† Один из способов обойти это - заставить браузер перезагрузить все, когда выйдет новая версия. Но для того, чтобы позволить завершению любых выполняемых операций, все же может быть проще поддерживать как минимум две версии параллельно: v-current и v-previous.

В Laravel (PHP) мы можем сделать это следующим ясным и элегантным способом (используя метку времени изменения файла):

<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>

И похоже на CSS

<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">

Не используйте foo.css? Version=1! Браузеры не должны кэшировать URL-адреса с помощью переменных GET. Согласно http://www.thinkvitamin.com/features/webapps/serving-javascript-fast, хотя IE и Firefox игнорируют это, Opera и Safari этого не делают! Вместо этого используйте foo.v1234.css и используйте правила перезаписи, чтобы удалить номер версии.

Вот чистое решение JavaScript

(function(){

    // Match this timestamp with the release of your code
    var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);

    var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');

    if(lastCacheDateTime){
        if(lastVersioning > lastCacheDateTime){
            var reload = true;
        }
    }

    localStorage.setItem('lastCacheDatetime', Date.now());

    if(reload){
        location.reload(true);
    }

})();

Выше будет выглядеть в последний раз, когда пользователь посетил ваш сайт. Если последний визит был до того, как вы выпустили новый код, он использует location.reload(true) принудительно обновить страницу с сервера.

У меня обычно это самый первый сценарий в <head> поэтому он оценивается перед загрузкой любого другого контента. Если требуется перезагрузка, это вряд ли заметно для пользователя.

Я использую локальное хранилище для хранения отметки времени последнего посещения в браузере, но вы можете добавить файлы cookie в список, если вы хотите поддерживать более старые версии IE.

RewriteRule нуждается в небольшом обновлении для файлов js или css, которые содержат версионную запись в конце. Например, json-1.3.js.

Я добавил класс отрицания точек [^.] В регулярное выражение, так что.number. игнорируется

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]

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

Это приведет к следующему:

<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />

Конечно, решения datetime также выполняют свою работу в случае редактирования файла CSS, но я думаю, что это касается содержимого файла css, а не файла datetime, так зачем смешивать их?

Для ASP.NET 4.5 и выше вы можете использовать связывание скриптов.

Запрос http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81 предназначен для пакета AllMyScripts и содержит пару строк запроса v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81. Строка запроса v имеет маркер значения, который является уникальным идентификатором, используемым для кэширования. Пока пакет не изменяется, приложение ASP.NET будет запрашивать пакет AllMyScripts, используя этот токен. Если какой-либо файл в пакете изменяется, среда оптимизации ASP.NET сгенерирует новый токен, гарантируя, что запросы браузера для пакета получат последний пакет.

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

Для моего развития я считаю, что хром имеет отличное решение.

https://developer.chrome.com/devtools/docs/tips-and-tricks

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

Это мой лучший друг, и это супер легкий способ получить то, что вы хотите!

Спасибо Кипу за его идеальное решение!

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

Надеюсь, это поможет кому-то еще.

/**
 * Extend filepath with timestamp to force browser to
 * automatically refresh them if they are updated
 *
 * This is based on Kip's version, but now
 * also works on virtual hosts
 * @link http://stackru.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files
 *
 * Usage:
 * - extend your .htaccess file with
 * # Route for My_View_Helper_AutoRefreshRewriter
 * # which extends files with there timestamp so if these
 * # are updated a automatic refresh should occur
 * # RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
 * - then use it in your view script like
 * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . 'default.css'));
 *
 */
class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract {

    public function autoRefreshRewriter($filePath) {

        if (strpos($filePath, '/') !== 0) {

            // path has no leading '/'
            return $filePath;
        } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . $filePath)) {

            // file exists under normal path
            // so build path based on this
            $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $filePath);
            return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
        } else {

            // fetch directory of index.php file (file from all others are included)
            // and get only the directory
            $indexFilePath = dirname(current(get_included_files()));

            // check if file exist relativ to index file
            if (file_exists($indexFilePath . $filePath)) {

                // get timestamp based on this relativ path
                $mtime = filemtime($indexFilePath . $filePath);

                // write generated timestamp to path
                // but use old path not the relativ one
                return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
            } else {

                return $filePath;
            }
        }
    }

}

Ура и спасибо.

Не нашли подход DOM на стороне клиента для динамического создания элемента узла сценария (или css):

<script>
    var node = document.createElement("script"); 
    node.type = "text/javascript";
    node.src = 'test.js?'+Math.floor(Math.random()*999999999);
    document.getElementsByTagName("head")[0].appendChild(node);
</script>

Скажем, у вас есть файл, доступный по адресу:

/styles/screen.css

Вы можете добавить параметр запроса с информацией о версии в URI, например:

/styles/screen.css?v=1234

или вы можете добавить информацию о версии, например:

/v/1234/styles/screen.css

ИМХО, второй метод лучше подходит для файлов CSS, потому что они могут ссылаться на изображения с использованием относительных URL, что означает, что если вы укажете background-image вот так:

body {
    background-image: url('images/happy.gif');
}

его URL будет эффективно:

/v/1234/styles/images/happy.gif

Это означает, что если вы обновите номер используемой версии, сервер будет воспринимать это как новый ресурс и не будет использовать кэшированную версию. Если вы основываете свой номер версии на Subversion/CVS/ и т.д. пересмотр означает, что будут замечены изменения в изображениях, на которые есть ссылки в файлах CSS. Это не гарантируется с первой схемой, то есть URL images/happy.gif относительно /styles/screen.css?v=1235 является /styles/images/happy.gif который не содержит никакой информации о версии.

Я реализовал решение для кэширования, используя эту технику с сервлетами Java, и просто обрабатываю запросы /v/* с сервлетом, который делегирует базовому ресурсу (т.е. /styles/screen.css). В режиме разработки я установил заголовки кэширования, которые говорят клиенту всегда проверять свежесть ресурса с сервером (обычно это приводит к 304, если вы делегируете Tomcat's DefaultServlet и .css, .jsи т. д. файл не изменился) в то время как в режиме развертывания я установил заголовки, которые говорят "кешировать навсегда".

В Google Chrome есть " Жесткая перезагрузка", а также " Очистить кэш" и "Жесткая перезагрузка". Вы можете нажать и удерживать кнопку перезагрузки (в режиме проверки), чтобы выбрать ее.

Вы можете просто добавить случайное число с помощью CSS/JS url, например

example.css?randomNo=Math.random()

Я недавно решил это с помощью Python. Вот код (должен быть легко адаптирован к другим языкам):

def import_tag(pattern, name, **kw):
    if name[0] == "/":
        name = name[1:]
    # Additional HTML attributes
    attrs = ' '.join(['%s="%s"' % item for item in kw.items()])
    try:
        # Get the files modification time
        mtime = os.stat(os.path.join('/documentroot', name)).st_mtime
        include = "%s?%d" % (name, mtime)
        # this is the same as sprintf(pattern, attrs, include) in other
        # languages
        return pattern % (attrs, include)
    except:
        # In case of error return the include without the added query
        # parameter.
        return pattern % (attrs, name)

def script(name, **kw):
    return import_tag("""<script type="text/javascript" """ +\
        """ %s src="/%s"></script>""", name, **kw)

def stylesheet(name, **kw):
    return import_tag('<link rel="stylesheet" type="text/css" ' +\
        """%s href="/%s">', name, **kw) 

Этот код в основном добавляет метку времени файлов в качестве параметра запроса к URL. Вызов следующей функции

script("/main.css")

приведет к

<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">

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

Вы можете принудительно использовать "кеширование всей сессии", если добавляете идентификатор сессии в качестве простого параметра файла js/css:

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

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

<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>

Для ASP.NET я предполагаю следующее решение с расширенными возможностями (режим отладки / выпуска, версии):

Файлы Js или Css включены таким образом:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfix и Global.CssPostfix вычисляются в Global.asax следующим образом:

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}

If you are a developer looking to avoid caching, chrome network tab has disable cache option. Otherwise you can do it without a server rendering framework using two script tags.

<script type="text/javascript">
    document.write('<script type="text/javascript" src="myfile.js?q=' + Date.now() + '">
    // can't use myfile.js stuff yet
</script>')
<script type="text/javascript">
    // do something with myfile.js
</script>

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

 $( window ).load(function() {
   location.reload(true);
});

Если вы используете git + php, вы можете перезагружать скрипт из кэша каждый раз, когда происходит изменение в git-репо, используя следующий код:

exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;

Этот вопрос очень старый и появляется первым делом, когда кто-то ищет его в Google. Это не ответ на вопрос так, как этого хочет op, а ответ разработчикам, которые столкнулись с этой проблемой при разработке и тестировании. И я не могу задать новый вопрос по этой теме, так как он будет помечен как повторяющийся.

Как и многие другие, я просто хотел ненадолго убрать кеширование.

"keep caching consistent with the file".. это слишком много хлопот..

Вообще говоря, я не против загрузки еще - даже повторная загрузка файлов, которые не изменились - в большинстве проектов - практически не имеет значения. При разработке приложения - в основном мы загружаемся с диска, наlocalhost:port - так это increase in network trafficпроблема не является проблемой нарушения сделки.

Большинство небольших проектов - это просто игра - они никогда не заканчиваются в производстве. так что для них больше ничего не нужно..

Таким образом, если вы используете Chrome Dev Tools, вы можете использовать этот метод отключения кеширования, как показано на изображении ниже:

И если у вас есть проблемы с кешированием Firefox:

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

Да, эта информация уже есть в предыдущих ответах, но мне все еще нужно было выполнить поиск в Google, чтобы найти ее.

Надеюсь, этот ответ очень ясен, и теперь вам это не нужно.

Кажется, что все ответы здесь предполагают какое-то управление версиями в схеме именования, которая имеет свои недостатки.

Браузеры должны хорошо знать, что кэшировать, а что нет, читая ответ веб-серверов, в частности, заголовки http - как долго этот ресурс действителен? был ли этот ресурс обновлен с тех пор, как я последний раз его получал и так далее.

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

Более подробное объяснение того, как это работает, можно найти здесь https://www.mnot.net/cache_docs/

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

В ASP.NET

<link rel="stylesheet" href="~/css/custom.css?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/css/custom.css")).ToString(),"[^0-9]", ""))" />

<script type="text/javascript" src="~/js/custom.js?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/js/custom.js")).ToString(),"[^0-9]", ""))"></script>    

Вы можете использовать SRI, чтобы сломать кеш браузера. Вам нужно только каждый раз обновлять ваш index.html новым хешем SRI. Когда браузер загружает HTML и обнаруживает, что хэш SRI на странице HTML не соответствует кэшированной версии ресурса, он перезагрузит ваш ресурс с ваших серверов. Это также имеет хороший побочный эффект - обход блокировки блокировки чтения.

<script src="https://jessietessie.github.io/google-translate-token-generator/google_translate_token_generator.js" integrity="sha384-muTMBCWlaLhgTXLmflAEQVaaGwxYe1DYIf2fGdRkaAQeb4Usma/kqRWFWErr2BSi" crossorigin="anonymous"></script>

Другие вопросы по тегам