Как правильно использовать контроль кэша "must-revalidate" для динамически загружаемого контента? - PullRequest
0 голосов
/ 27 июня 2018

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

Итак, я просмотрел много статей о стековом потоке, касающихся must-revalidate. Исходя из этого, я реализовал заголовки кэша, чтобы они выглядели так:

Cache-Control: must-revalidate,max-age=0

У меня также включен ETag. Из того, что я прочитал и понял, это должно проверять изменения и загружать, только если есть какие-либо изменения

Проблема заключается в том, что как в Firefox, так и в Chrome файл загружается независимо от того, есть изменения или нет. т.е. даже когда файл и Etag не изменены, браузер НЕ загружается из кеша.

Что происходит в этом случае? Я что-то здесь не так делаю? я должен установить длинный maxage, когда я использую must-revalidate вместо maxage, установленного в ноль?

Я редактирую этот вопрос, потому что нашел что-то важное во время дальнейшей проверки. пожалуйста, прочитайте ниже, прежде чем отправлять ответ.

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

, например: если у меня есть тег сценария на странице источника

<script src="some-js.js" type="text/javascript">

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

однако, если тег scritp загружается динамически (вставьте мой код для загрузки тега динамического скрипта ниже)

var s = document.createElement('script');
s.setAttribute('src', 'newjs.js');
s.setAttribute('id', 'script1');
s.type = 'text/javascript';
s.async = false;
s.onerror = errorcallback;
s.onload = loadcallback;
document.body.appendChild(s);

этот js всегда перезагружается независимо от заголовка кэша.

Есть идеи, почему это происходит?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Он перезагружает файл каждый раз, потому что вы деактивируете любой тип кэша с помощью max-age=0.

Существует два способа, с помощью которых браузер может проверить, устарел ли файл, который находится в кэше:

  • ETags
  • время модификации

Оба требуют, чтобы браузер содержал файл в кеше, в противном случае ему не с чем работать. Чтобы браузер сохранял файл в кеше, ему должно быть разрешено некоторое время хранить его в кеше. Это делается путем указания заголовка max-age и / или Expires. Если это 0, то браузер ничего не будет кэшировать. Итак, сначала разрешите браузеру вообще кэшировать файл, установив положительное время истечения.

Далее must-revalidate указывает, что браузер должен проверить на сервере, доступен ли более новый файл. Если это так, сервер отправит более новый файл, в противном случае сервер ответит кодом состояния HTTP, указывающим, что браузер по-прежнему имеет последнюю версию, и не будет отправлять длинное тело ответа. Чтобы это работало, должен существовать механизм, который браузер и сервер могут использовать для подтверждения содержимого файла. Вот тут-то и появляются ETag или времена модификации.

Если ваш сервер устанавливает заголовок ETag для файла, который обычно содержит хэш содержимого файла, тогда браузер может проверить его, запросив его с заголовком If-None-Match. Если ETag файла все еще совпадает, сервер ответит 304 Not Modified.
Другой альтернативой для сервера является установка заголовка Last-Modified, который позволяет браузеру запрашивать файл с помощью If-Modified-Since, а сервер снова отвечает 304 Not Modified, если файл все еще актуален.

Без must-revalidate браузер будет просто использовать кэшированную версию файла, не обращаясь к серверу вообще, пока не будет достигнуто время max-age / Expires файла, а затем он может запросить файл снова с помощью If-None-Match / If-Modified-Since. С директивой must-revalidate браузер получает указание проверять сервер каждый раз перед использованием кэшированного файла.

0 голосов
/ 27 июня 2018

Переименуйте файл JS, чтобы имя содержало хэш содержимого файла, например: your_module.489d43f35d9b718c5cdc4f0828a7c6c7.js, и пометьте файл как неизменный . Таким образом, клиент загрузит файл только один раз.

Если содержимое файла изменится, просто сгенерируйте новое имя файла на основе нового содержимого. Этот метод часто используется в Webpack bundler. Больше не нужно играть с заголовками!

...