2010-11-17 2 views
20

Так мы предотвращаем кеширование файлов JS и CSS браузерами. Это кажется немного взломанным .. есть ли лучший способ?Лучший способ предотвратить кеширование браузером файлов JavaScript

<% 
//JSP code 
long ts = (new Date()).getTime(); //Used to prevent JS/CSS caching 
%> 

<link rel="stylesheet" type="text/css" media="screen" href="/css/management.css?<%=ts %>" /> 
<script type="text/javascript" src="/js/pm.init.js?<%=ts %>"></script> 
<script type="text/javascript" src="/js/pm.util.func.js?<%=ts %>"></script> 

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

+3

Нужно ли им загружать каждую загрузку страницы или просто когда вы делаете новый выпуск? –

+2

Да, почему в мире вы хотели бы * предотвратить * кэширование своего статического контента? Это как полная противоположность тому, что люди обычно делают. – Pointy

+2

@Nick Craver & Pointy: Может быть, он отлаживает и не хочет очищать кеш каждый раз? Это все, что я могу понять. – Robusto

ответ

20

Вы хотите, чтобы CSS и JS были кэшированы. Это ускоряет загрузку веб-страницы, когда они возвращаются. Добавляя временную метку, ваш пользователь будет вынужден снова и снова загружать ее.

Если вы хотите, чтобы у них всегда была новая версия, ваша система сборки добавит номер сборки в конец файла вместо метки времени.

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

+0

«Добавляя отметку времени, ваш пользователь будет вынужден снова и снова загружать его». (Это имеет смысл). Но потом вы сказали: «Если вы хотите убедиться, что у них всегда есть новая версия, чем ваша система сборки добавит номер сборки в конец файла вместо метки времени». (Это, похоже, противоречит вашему первому утверждению). – AlvinfromDiaspar

+1

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

17

Кэширование - ваш друг. Если браузеры кэшируют эти файлы неправильно, это означает, что что-то не так с заголовками HTTP, которые ваш веб-сервер отправляет вместе с самими файлами JS и CSS (а не с HTML-страницей, которая их использует). Браузер использует эти заголовки, чтобы выяснить, может ли он кэшировать файл.

Ваш веб-сервер может отправить эти заголовки (на каждом JS и CSS файл он служит) сообщить браузеру не кэшировать их:

Cache-Control: no-cache 
Pragma: no-cache 
Expires: Sat, 01 Jan 2000 00:00:00 GMT 

Но это увеличит нагрузку на сеть на вашем сайте, и пользователи будут см. страницу загрузки медленнее. Вы могли бы быть немного более мягким и позволяет браузеру кэшировать файл CSS в течение 60 секунд:

Cache-Control: max-age=60 

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

Cache-Control: max-age=0 
Pragma: no-cache 
Expires: Sat, 01 Jan 2000 00:00:00 GMT 
ETag: "o2389r-98ur0-w3894tu-q894" 

ETag это просто уникальный идентификатор веб-сервер делает каждый раз изменения файла. В следующий раз, когда браузеру понадобится файл, он спрашивает сервер: «У /js/pm.init.js все еще есть ETag o2389r98ur0w3894tuq894?» и если да, то ваш сервер просто говорит «да». Таким образом, вашему серверу больше не придется отправлять весь файл, и пользователю не нужно ждать его загрузки. Беспроигрышная.

Как убедить ваш веб-сервер в автогенерации ETags зависит от сервера. Обычно это не сложно.

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

1

Для целей отладки, установите web developer toolbar для FireFox и активировать там "отключить кэш"

Update:
Когда вы установили FireBug, вы можете disable caching as well in the network tab settings.

+1

У нас есть аналогичный инструмент для Chrome? – Raghav

+1

Google Chrome поставляется с Chrome Developer Tools, встроенным в браузер. если вы откроете Chrome Dev Tools, вы увидите шестерню в нижнем правом углу. Нажмите на это и установите флажок «Отключить кеш» в заголовке «Общие». – Matt

11

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

Для этого вы хотите, чтобы значение «ts» было связано с файлом не со временем дня. Вы можете использовать один из этих систем:

  1. ц = Отметка части файла
  2. ц = MD5 (или какой-либо контрольная сумма) файла
  3. ц = версия кода. Если у вас есть сценарий, который делает развертывание, убедитесь, что он добавляет код версии (или дату выпуска) в некоторый файл include, который будет назначен для ts.

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

3

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

3

Редактировать

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

Все, что вам нужно сделать, это добавить это application.properties:

spring.resources.chain.strategy.content.enabled=true 
spring.resources.chain.strategy.content.paths=/** 

Если вы используете Thymeleaf или FreeMarker это полностью автоконфигурации. Если вы используете JSP, вам нужно вручную объявить ResourceUrlEncodingFilter.

Подробнее здесь: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-static-content

Что следует теперь мой «старый» пост, который также работает, но требует больше работы.


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

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

К счастью, maven может сделать все это для вас во время сборки. Вам понадобятся minify-maven-plugin и maven-replacer-plugin.

Этот отрывок из pom.xml поможет вам начать:

<properties> 
    <timestamp>${maven.build.timestamp}</timestamp> 
    <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format> 
</properties> 

<plugin> 
    <groupId>com.samaxes.maven</groupId> 
    <artifactId>minify-maven-plugin</artifactId> 
    <version>1.6</version> 
    <executions> 
     <execution> 
      <id>minify-css</id> 
      <phase>process-resources</phase> 
      <goals> 
       <goal>minify</goal> 
      </goals> 
      <configuration> 
       <linebreak>-1</linebreak> 
       <cssSourceDir>resources/css</cssSourceDir> 
       <cssSourceFiles> 
        <cssSourceFile>bootstrap.css</cssSourceFile> 
        <cssSourceFile>style.css</cssSourceFile> 
       </cssSourceFiles> 
       <cssTargetDir>resources/css</cssTargetDir> 
       <cssFinalFile>${timestamp}.css</cssFinalFile> 
      </configuration> 
     </execution> 
     <execution> 
      <id>minify-js</id> 
      <phase>process-resources</phase> 
      <goals> 
       <goal>minify</goal> 
      </goals> 
      <configuration> 
       <linebreak>-1</linebreak> 
       <jsSourceDir>resources/js</jsSourceDir> 
       <jsSourceFiles> 
        <jsSourceFile>jquery.js</jsSourceFile> 
        <jsSourceFile>bootstrap.js</jsSourceFile> 
        <jsSourceFile>script.js</jsSourceFile> 
       </jsSourceFiles> 
       <jsTargetDir>resources/js</jsTargetDir> 
       <jsFinalFile>${timestamp}.js</jsFinalFile> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

<plugin> 
    <groupId>com.google.code.maven-replacer-plugin</groupId> 
    <artifactId>replacer</artifactId> 
    <version>1.5.2</version> 
    <executions> 
     <execution> 
      <id>replaceDynPartInResourcePath</id> 
      <phase>prepare-package</phase> 
      <goals> 
       <goal>replace</goal> 
      </goals> 
      <configuration> 
       <ignoreMissingFile>false</ignoreMissingFile> 
       <basedir>${project.build.directory}</basedir> 
       <file>${project.artifactId}/WEB-INF/views/header.jsp</file> 
       <regex>false</regex> 
       <replacements> 
        <replacement> 
         <token>$dynamicResourceNamePart$</token> 
         <value>${timestamp}</value> 
        </replacement> 
       </replacements> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

Это как включить ваши статические ресурсы в заголовке.JSP

<c:choose> 
    <c:when test="${not fn:contains(pageContext.request.serverName, 'localhost') and empty param.nocombine}"> 
     <link href="${pageContext.request.contextPath}/resources/css/$dynamicResourceNamePart$.min.css" rel="stylesheet" type="text/css" /> 
     <script src="${pageContext.request.contextPath}/resources/js/$dynamicResourceNamePart$.min.js" type="text/javascript"></script> 
    </c:when> 
    <c:otherwise> 
     <link href="${pageContext.request.contextPath}/resources/css/bootstrap.css" rel="stylesheet"> 
     <link href="${pageContext.request.contextPath}/resources/css/style.css" rel="stylesheet"> 
     <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/jquery.js"></script> 
     <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/bootstrap.js"></script> 
     <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/script.js"></script> 
    </c:otherwise> 
</c:choose> 
0

Если вы можете включить Java Servlet фильтра в приложении, вот рабочий раствор: CorrectBrowserCacheHandlerFilter.java

В основном, когда ваш браузер запрашивает статические файлы, сервер перенаправляет каждые запросы на то же самое но с параметром хэш-запроса (например, ?v=azErT), который зависит от содержимого целевого статического файла.

Делая это, браузер никогда не кэшировать статические файлы, объявленные в вашем index.html, например, (потому что всегда получает 302 Moved Temporarily), но будет кэшировать только те, с хэш-версии (сервер ответит 200 для них). Таким образом, кеш браузера будет эффективно использоваться для этих статических файлов с хэш-версией.

Отказ от ответственности: Я являюсь автором CorrectBrowserCacheHandlerFilter.java.

Смежные вопросы