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

Самый простой способ - с помощью некоторой магии ES6:

Слияние двух с дубликатами:

const a = [{a: 1}, {b: 2}]
const b = [{a: 1}]

const result = a.concat(b) // [{a: 1}, {b: 2}, {a: 1}]

Без дубликатов это то же самое, что и выше:

const distinct = [...new Set(result.map(item => item.YOUR_PROP_HERE))]

942
задан 9 revs, 4 users 35% 14 May 2019 в 13:23
поделиться

16 ответов

Мой метод, чтобы сделать это должно просто иметь элемент ссылки в серверную сторону, включайте:

<!--#include virtual="/includes/css-element.txt"-->

, где содержание css-element.txt

<link rel="stylesheet" href="mycss.css"/>

так день, Вы хотите связаться с my-new-css.css или что бы то ни было, Вы просто изменяете включать.

0
ответ дан AmbroseChapel 14 May 2019 в 13:23
поделиться

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

-1
ответ дан roundcrisis 14 May 2019 в 13:23
поделиться

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

Обновление 2: Слияние комментариев от Nick Johnson, что оригинал .htaccess regex может вызвать проблемы с файлами как json-1.3.js. Решение состоит в том, чтобы только переписать, если существует точно 10 цифр в конце. (Поскольку 10 цифр покрывают все метки времени с 09.09.2001 до 20.11.2286.)

Во-первых, мы используем следующее, переписывают правило в .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" />

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

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

447
ответ дан Benjamin 14 May 2019 в 13:23
поделиться

Изменение имени файла будет работать. Но это обычно не простое решение.

заголовок управления кэша HTTP 'без кэшей' не всегда работает, как Вы заметили. Спецификация HTTP 1.1 позволяет пространству для маневра для агентов пользователя решать, запросить ли новую копию. (Это неинтуитивно, если Вы просто смотрите на названия директив. Пойдите читает фактическое спецификация HTTP 1.1 для кэша ..., это имеет немного больше смысла в контексте.)

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

Cache-Control: no-cache, no-store, must-revalidate

в Ваших заголовках ответа.

-3
ответ дан pcorcoran 14 May 2019 в 13:23
поделиться

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

, Таким образом, Ваш URL был бы чем-то как

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

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

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

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

91
ответ дан levik 14 May 2019 в 13:23
поделиться

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

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

<час>

Примечание: существует некоторый аргумент относительно точно, как это влияет на кэширование. Я полагаю, что общая суть его, это ПОЛУЧАЕТ запросы, с или без параметров должен быть реализуемым, таким образом, вышеупомянутое решение должно работать.

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

51
ответ дан SCdF 14 May 2019 в 13:23
поделиться

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

14
ответ дан airrob 14 May 2019 в 13:23
поделиться

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

См. также:

39
ответ дан John Millikin 14 May 2019 в 13:23
поделиться

Я предлагаю реализовать следующий процесс:

  • присваивают версию Вашим css/js файлам каждый раз, когда Вы развертываетесь, что-то как: экран 1233.css (число может быть Вашим пересмотром SVN при использовании системы управления версиями)

  • уменьшает их для оптимизации загружающихся времен

2
ответ дан Dan Burzo 14 May 2019 в 13:23
поделиться

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

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

у Общих посетителей Вашего веб-сайта не будет того же опыта, который Вы имеете при разработке сайта. Так как средний посетитель приезжает в сайт менее часто (возможно, только несколько раз каждый месяц, если Вы не будете 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. То, когда браузер выполняет запрос к серверу, часть ответа, ИСТЕКАЕТ заголовок.. дата, которая говорит браузер, сколько времени это должно быть сохранено в кэше. В следующий раз, когда браузер сталкивается с запросом на тот же файл, он видит, что имеет копию в кэше и смотрит, ИСТЕКАЕТ дата, чтобы решить, должен ли он использоваться.

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

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

180
ответ дан BraveNewMath 14 May 2019 в 13:23
поделиться

Можно вызвать "кэширование всей сессии", если Вы добавляете идентификатор сессии как побочный параметр 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>
5
ответ дан helios 14 May 2019 в 13:23
поделиться

Скажите, что Вы имеете файл в наличии в:

/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

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

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

5
ответ дан 2 revs 14 May 2019 в 13:23
поделиться

Я недавно решил это использование 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 автоматически инициирует аннулирование кэша. Очень хорошие работы и издержки не примечательны.

4
ответ дан pi. 14 May 2019 в 13:23
поделиться

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

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

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

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

8
ответ дан 19 December 2019 в 20:21
поделиться

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

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

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
10
ответ дан 19 December 2019 в 20:21
поделиться

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

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

"keep caching consistent with the file".. слишком много стычки..

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

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

Как таковой, если Вы используете Chrome Инструменты Dev , можно следовать, это отключает кэширующийся подход как в изображении ниже: how to force chrome to reload cached files

И если Вы имеете проблемы кэширования firefox: how to force asset reload on firefox

how to disable caching in Firefox while in development Делают это только в разработке, Вам также нужен механизм для принуждения перезагрузки для производства, так как пользователи будут использовать делаемые недействительным модули старого кэша, если Вы будете часто обновлять свое приложение, и Вы не обеспечиваете выделенный механизм синхронизации кэша как те описанные в ответах выше.

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

, Надо надеяться, этот ответ является очень четким, и теперь Вы не должны.

0
ответ дан 19 December 2019 в 20:21
поделиться
Другие вопросы по тегам:

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