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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4206224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:22:28  来源:igfitidea点击:

Better way to prevent browser caching of JavaScript files

javascriptjquerycsscachingjsp

提问by Marcus Leon

This is how we prevent caching of JS and CSS files by browsers. This seems slightly hacky.. is there a better way?

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


Update: The reason we want to prevent caching is to ensure the newer version of the files are loaded when we do a new release.

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

采纳答案by epascarello

You want CSS and JS to be cached. It speeds up the loading of the web page when they come back. Adding a timestamp, your user's will be forced to download it time and time again.

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

If you want to make sure they always have a new version, than have your build system add a build number to the end of the file instead of a timestamp.

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

If you have issues with it just in dev, make sure to set up your browsers to not cache files or set headers on your dev pages to not cache.

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

回答by Jason Orendorff

Caching is your friend. If browsers are caching these files incorrectly, it means something is wrong with the HTTP headers your web server is sending along with the JS and CSS files themselves (not the HTML page that uses them). The browser uses those headers to figure out if it can cache the file.

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

Your Web server can send these headers (on every JS and CSS file it serves) to tell browsers not to cache them:

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

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

But that will increase the network load on your site, and users will see the page load slower. You could be a little more lenient and allow the browser to cache the CSS file for 60 seconds:

但这会增加您网站上的网络负载,用户会看到页面加载速度变慢。您可以稍微宽容一点,并允许浏览器将 CSS 文件缓存 60 秒:

Cache-Control: max-age=60

If you really want the browser to check for a new file with every single page load, you can stillsave some network traffic by using an ETag:

如果您真的希望浏览器在每次加载页面时检查新文件,您仍然可以通过使用 ETag 来节省一些网络流量:

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

The ETag is simply a unique identifier your Web server makes up each time the file changes. The next time the browser wants the file, it asks the server, "does /js/pm.init.js still have the ETag o2389r98ur0w3894tuq894?" and if so, your server simply says, "yes". That way your server doesn't have to send the whole file again, and the user doesn't have to wait for it to load. Win-win.

ETag 只是您的 Web 服务器在每次文件更改时组成的唯一标识符。下一次浏览器想要该文件时,它会询问服务器,“/js/pm.init.js 是否还有 ETag o2389r98ur0w3894tuq894?” 如果是这样,您的服务器只会说“是”。这样你的服务器就不必再次发送整个文件,用户也不必等待它加载。双赢。

How to convince your web server to autogenerate ETags depends on the server. It's usually not hard.

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

I've seen the hack you're using before. Like so much on the Web, it's not pretty or particularly efficient, but it works.

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

回答by Chris Cinelli

If The reason we want to prevent caching is to ensure the newer version of the files are loaded when we do a new release., you want that the new js is loaded when THERE IS a NEW release, not all the times.

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

In order to do that you want that the "ts" value is linked with the file not with the time of the day. You can either use one of these system:

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

  1. ts = Timestamp OF THE FILE
  2. ts = MD5 (or whatever checksum) of the FILE
  3. ts = version of the code. If you have a script that do deployment be sure that it adds the version code (or the date of the release) in some include file that will be assigned to ts.
  1. ts = 文件的时间戳
  2. ts = 文件的 MD5(或任何校验和)
  3. ts = 代码版本。如果您有一个执行部署的脚本,请确保它在将分配给 ts 的某些包含文件中添加版本代码(或发布日期)。

In this way the browser will reload the file only if it is new and not all the times.

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

回答by user2784850

A simple approach to this would be to use last modified date of the js or css files in the URL instead of a time stamp. This would have the effect of preventing caching only when there is a new version of the file on the server.

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

回答by yglodt

Edit

编辑

In case you are using Spring Boot it's now much simpler to prevent caching of modified files.

如果您正在使用 Spring Boot,现在防止缓存修改的文件要简单得多。

All you need to do is add this to application.properties:

您需要做的就是将其添加到 application.properties 中:

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

If you are using Thymeleaf or FreeMarker it's completely autoconfigured. If you are using JSPs you need to manually declare a ResourceUrlEncodingFilter.

如果您使用的是 Thymeleaf 或 FreeMarker,它是完全自动配置的。如果您使用 JSP,则需要手动声明 ResourceUrlEncodingFilter。

Read more here: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-static-content

在此处阅读更多信息:http: //docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-static-content

What follows now is my "old" post which also works but requires more work.

现在接下来是我的“旧”帖子,它也有效,但需要更多的工作。



Since you are using Java there is a chance you are also using maven to manage your project.

由于您使用的是 Java,因此您也有可能使用 maven 来管理您的项目。

In that case, to improve performance, and to make sure that no browser caches your static resources when a new release of your software is produced, you should combine all of your stylesheets and JavaScript files into on single file of their type, and you should make your resource urls change when you create a new release.

在这种情况下,为了提高性能,并确保在您的软件的新版本发布时没有浏览器缓存您的静态资源,您应该将所有样式表和 JavaScript 文件合并到它们类型的单个文件中,并且您应该在创建新版本时更改资源 url。

Luckily maven can do all this for you at build-time. You'll need minify-maven-pluginand maven-replacer-plugin.

幸运的是,maven 可以在构建时为您完成所有这些工作。你需要minify-maven-pluginmaven-replacer-plugin

This excerpt of a pom.xml should get you started:

这个 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>

This is how to include your static resources in header.jsp

这是在 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>

回答by powtac

For debug purposes, install the web developer toolbarfor FireFox and activate there "deactivate Cache"

出于调试目的,请安装FireFox的Web 开发人员工具栏并在那里激活“停用缓存”

Update:
When you have FireBug installed, you can disable caching as well in the network tab settings.

更新:
安装 FireBug 后,您还可以在网络选项卡设置中禁用缓存

回答by Anthony O.

If you can include Java Servlet Filter in your application, here is a working solution: CorrectBrowserCacheHandlerFilter.java

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

Basically, when your browser requests the static files, the server will redirect every requests to the same one but with a hash query parameter (?v=azErTfor example) which depends on the content of the target static file.

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

Doing this, the browser will never cache the static files declared in your index.htmlfor example (because will always received a 302 Moved Temporarily), but will only cache the ones with the hash version (the server will answer 200for them). So the browser cache will be used efficiently for those static files with hash version.

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

Disclaimer: I'm the author of CorrectBrowserCacheHandlerFilter.java.

免责声明:我是CorrectBrowserCacheHandlerFilter.java.