防止JavaScript文件的浏览器缓存的更好方法

时间:2010-11-17 15:50:49

标签: javascript jquery css caching jsp

这是我们阻止浏览器缓存JS和CSS文件的方法。这似乎有点hacky ..有更好的方法吗?

<%
//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 个答案:

答案 0 :(得分:22)

您希望缓存CSS和JS。当它们返回时,它加速了网页的加载。添加时间戳,您的用户将被迫一次又一次地下载。

如果你想确保他们总是拥有一个新版本,那么让你的构建系统在文件的末尾添加一个内部版本号而不是一个时间戳。

如果您只是在dev中遇到问题,请确保将浏览器设置为不缓存文件或将开发页面上的标题设置为不缓存。

答案 1 :(得分:17)

缓存是你的朋友。如果浏览器错误地缓存这些文件,则表示Web服务器与JS和CSS文件本身(而不是使用它们的HTML页面)一起发送的HTTP标头出现问题。浏览器使用这些标头来确定它是否可以缓存文件。

您的Web服务器可以发送这些标头(在它提供的每个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只是每次文件更改时Web服务器组成的唯一标识符。下次浏览器需要该文件时,它会询问服务器“/js/pm.init.js是否还有ETag o2389r98ur0w3894tuq894?”如果是这样,你的服务器只是说“是”。这样,您的服务器不必再次发送整个文件,用户不必等待它加载。双赢。

如何说服您的Web服务器自动生成ETag取决于服务器。这通常不难。

我以前见过你正在使用的黑客。就像在网上这么多,它不是很漂亮或特别有效,但它有效。

答案 2 :(得分:11)

如果我们想要阻止缓存的原因是为了确保在我们执行新版本时加载更新版本的文件。,您希望在有新版本时加载新的js释放,而不是所有时间。

为了做到这一点,你希望“ts”值与文件链接而不是与一天中的时间相关联。 您可以使用以下系统之一:

  1. ts =文件的时间戳
  2. ts =文件的MD5(或任何校验和)
  3. ts =代码的版本。如果您有一个执行部署的脚本,请确保它在一些将分配给ts的包含文件中添加版本代码(或发布日期)。
  4. 通过这种方式,只有在新文件出现时,浏览器才会重新加载文件。

答案 3 :(得分:3)

一种简单的方法是使用URL中js或css文件的最后修改日期而不是时间戳。只有当服务器上有新版本的文件时,这才能防止缓存。

答案 4 :(得分:3)

修改

如果您使用的是Spring Boot,现在可以更加简单地防止缓存已修改的文件。

您需要做的就是将其添加到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-pluginmaven-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>

这是如何在header.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>

答案 5 :(得分:1)

出于调试目的,为FireFox安装web developer toolbar并在那里激活“deactivate Cache”

<强>更新
安装FireBug后,您可以disable caching as well in the network tab settings

答案 6 :(得分:0)

如果您可以在应用程序中包含Java Servlet Filter,这是一个可行的解决方案:CorrectBrowserCacheHandlerFilter.java

基本上,当您的浏览器请求静态文件时,服务器会将每个请求重定向到同一个请求,但使用哈希查询参数(例如?v=azErT),这取决于目标静态文件的内容。 / p>

这样做,浏览器永远不会缓存在index.html中声明的静态文件(因为它总是会收到302 Moved Temporarily),但只会缓存带有哈希版本的服务器(服务器)将为他们回答200。因此,浏览器缓存将有效地用于具有哈希版本的静态文件。

免责声明:我是CorrectBrowserCacheHandlerFilter.java的作者。