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

IT技术 javascript jquery css caching jsp
2021-03-14 07:00:25

这就是我们如何防止浏览器缓存 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> 

更新:我们想要阻止缓存的原因是为了确保在我们发布新版本时加载较新版本的文件。

6个回答

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

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

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

“在您的开发页面上设置标题以不缓存。”。这些天你是如何做到这一点的?
2021-04-21 07:00:25
有什么理由在 js 文件名更改时附加一些内容吗?为什么不直接使用Cache-Control: no-cache
2021-05-03 07:00:25
“添加时间戳,您的用户将被迫一次又一次地下载它。” (这是有道理的)。但是你说,“如果你想确保他们总是有一个新版本,那么让你的构建系统在文件末尾添加一个构建号而不是时间戳。” (这似乎与您的第一个陈述相矛盾)。
2021-05-10 07:00:25
喜欢 8 岁的问题得到评论。好吧,你每次更新,另一个你只在它改变时更新。理想情况下,您设置了正确的缓存标头,而您不需要这样做。
2021-05-12 07:00:25

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

您的 Web 服务器可以发送这些标头(在它服务的每个 JS 和 CSS 文件上)以告诉浏览器不要缓存它们:

Cache-Control: no-store
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 取决于服务器。通常并不难。

我见过你以前使用的黑客。就像 Web 上的许多内容一样,它并不漂亮或特别高效,但它确实有效。

好的,我改了。no-cache根据确切的问题可能会更好,但这no-store是完全禁止缓存的设置。我希望这些天能减少动态生成的 JS 和 CSS!
2021-04-24 07:00:25
“告诉浏览器不要缓存它们:”-您提供的示例具有no-cache,我认为您打算使用no-store,对吗?
2021-04-27 07:00:25

如果我们想要阻止缓存的原因是为了确保在我们进行新版本发布时加载较新版本的文件。,您希望在有新版本时加载新的 js,而不是每次都加载。

为此,您希望“ts”值与文件相关联,而不是与一天中的时间相关联。您可以使用以下系统之一:

  1. ts = 文件的时间戳
  2. ts = 文件的 MD5(或任何校验和)
  3. ts = 代码版本。如果您有一个执行部署的脚本,请确保它在将分配给 ts 的某些包含文件中添加版本代码(或发布日期)。

通过这种方式,浏览器只会在文件是新文件时重新加载文件,而不是所有时间。

为什么不直接使用Cache-Control: no-cache呢?
2021-04-23 07:00:25

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

编辑

如果您使用的是 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>
@Me_developer:如果您使用 Spring Boot,并且为您的 js 和 css 文件 src-tags 使用 <c:url ... /> 或 <spring:url .../> 标签,那么是的。
2021-04-26 07:00:25
嗨,@yglodt 我只是想更好地理解。现在在我的每个 JSP 文件中,我都包含了我的 js 和 css 文件,例如“<script src="/js/common.js?v=<%= new java.util.Date() %>"></script> ”。但这是一种糟糕的实现方式。那么在我开始使用“spring.resources.chain.strategy.content.enabled=true”之后,我可以从我的 js 和 css 文件中删除“java.util.Dae()”吗?
2021-05-01 07:00:25
是的,我在 JSP 中使用 Spring Boot 和 jquery。所以现在我像这样使用它 "<script src="<c:url value="/js/common.js" />"></script>" 和我的 css 文件一样,"<link rel ="样式表" href="<c:url value="/css/createGroup.css" />">"。我希望我没有做错什么?我还手动声明了 'addResourceHandlers' 和 'ResourceUrlEncodingFilter' bean。谢谢。
2021-05-04 07:00:25