Лучший способ предотвратить кеширование браузером файлов JavaScript - PullRequest
22 голосов
/ 17 ноября 2010

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

<%
//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> 

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

Ответы [ 7 ]

22 голосов
/ 17 ноября 2010

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

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

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

18 голосов
/ 17 ноября 2010

Кэширование - твой друг.Если браузеры неправильно кэшируют эти файлы, это означает, что что-то не так с заголовками 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?»и если это так, ваш сервер просто говорит «да».Таким образом, вашему серверу не нужно снова отправлять весь файл, и пользователю не нужно ждать, пока он загрузится.Беспроигрышный вариант.

Способ убеждения вашего веб-сервера в автоматической генерации ETag зависит от сервера.Обычно это не сложно.

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

13 голосов
/ 17 ноября 2010

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

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

  1. ts = метка времени ФАЙЛА
  2. ts = MD5 (или любая другая контрольная сумма) ФАЙЛА
  3. ts = версиякода.Если у вас есть сценарий, который выполняет развертывание, убедитесь, что он добавляет код версии (или дату выпуска) в некоторый включаемый файл, который будет назначен ts.

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

3 голосов
/ 07 марта 2015

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

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

Все, что вам нужно сделать, это добавить это в приложение.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>
3 голосов
/ 16 сентября 2013

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

1 голос
/ 17 ноября 2010

В целях отладки установите панель инструментов веб-разработчика для FireFox и активируйте там "деактивировать кэш"

Обновление:
Когда у вас установлен FireBug, вы можете отключить кэширование, а также в настройках вкладки сети .

0 голосов
/ 13 декабря 2016

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...