目录
如何缓存 JavaScript、CSS 文件是一个关注点,因为这能显著提升网站性能、减少服务器负载、节省带宽。简而言之,缓存是指浏览器存储网页资源的一种机制,使得用户在访问同一页面时,无需重新下载相同的资源。特别地,对于JavaScript和CSS文件,一旦缓存,就可以在用户的后续访问中使用本地副本,这样可以加快页面加载速度、改善用户体验。其中,最常用的缓存实现方式包括设置HTTP缓存标头,如Cache-Control和Expires,以及使用服务工作器(Service Workers)。
一、HTTP缓存头的使用
HTTP缓存标头是控制缓存行为的一种方式。通过设置这些标头,服务器可以指示浏览器应如何以及在多长时间内缓存资源。两个关键的缓存标头是Cache-Control和Expires。
Cache-Control和Expires标头
- CACHE-CONTROL
Cache-Control标头可以精细控制缓存策略。它允许服务器指定资源在多久后变得“过时”,或者是否应该永不缓存。例如:Cache-Control: max-age=31536000告诉浏览器资源可以缓存并在接下来的一年内使用。
-
公共和私有缓存
Cache-Control还可以定义资源是应该被多个用户共享(公共缓存)还是只能由单个用户(私有缓存)缓存。 -
缓存重新验证
另一种选项是
must-revalidate,它强迫浏览器在使用缓存的资源前,先向服务器确认资源是否有更新。
- EXPIRES
Expires标头提供了一个HTTP日期/时间戳,它告诉浏览器在这个时间点之前可以直接使用缓存的资源,不需要再发送请求到服务器。Expires是HTTP/1.0标准的一部分,而Cache-Control是HTTP/1.1引入的,现代浏览器支持这两种标头。
- Expires与Cache-Control的关系
当同时存在时,现代浏览器更倾向于使用Cache-Control标头的指示。
在HTTP协议中,Cache-Control的优先级高于Expires。 当HTTP响应头中同时存在Expires和Cache-Control时,Cache-Control的优先级更高,会覆盖Expires的设置。
Cache-Control和Expires的区别
Expires和Cache-Control都是HTTP协议中用于控制缓存的有效期,但它们在定义和使用上有一些关键区别:
1、定义和格式:
① Expires:Expires是一个HTTP响应头,用于指定资源的过期时间,格式为GMT时间。它告诉客户端在什么时间之后不再使用这个缓存资源。
② Cache-Control:Cache-Control是一个更灵活的缓存控制机制,特别是在HTTP 1.1版本中引入。它通过不同的指令(如max-age)来控制缓存行为,格式为Cache-Control: max-age=<seconds>。Cache-Control不仅可以出现在响应头中,也可以出现在请求头中。
2、计算方式:
① Expires:是一个绝对时间值,表示资源在服务器上的过期时间。如果客户端时间与服务端时间不一致,可能会导致缓存失效。
Expires指定一个具体的过期时间点,依赖于服务器的时钟和客户端的时钟必须同步,否则可能会导致缓存失效。
② Cache-Control:是一个相对时间值,使用max-age指令表示资源在缓存中的最大有效时间。不受客户端时间的影响,因此更加可靠。
Cache-Control: max-age中的max-age指定从响应返回的时间开始计算的过期时间,单位是秒。这种方式不受服务器和客户端时钟同步问题的影响,因为它是基于相对时间计算的
3、适用性和灵活性:
① Expires:主要用于HTTP/1.0,但在HTTP/1.1中已被Cache-Control替代。由于时间同步问题,Expires的可靠性较低。
Expires相对简单,但容易受到时钟同步问题的影响。适用于HTTP 1.0版本,主要用于指定资源的具体过期时间
② Cache-Control:在HTTP/1.1中引入,提供了更灵活的缓存控制机制,包括max-age、no-cache、no-store等指令,能够更精确地控制缓存行为。
更加灵活和强大,能够适应不同的缓存需求,并且不受时钟同步问题的影响。适用于HTTP 1.1版本,提供了更细粒度的缓存控制策略,包括max-age、no-cache、no-store等指令,适用于更复杂的缓存需求
缓存机制的基本概念
- 强缓存:通过Expires和Cache-Control实现,当资源命中强缓存时,客户端直接从缓存中读取内容,返回HTTP状态码200。
- 协商缓存:当强缓存失效时,客户端会向服务器发送请求,服务器通过304响应告诉客户端资源未修改,客户端继续使用缓存内容。
综上所述,Cache-Control由于其灵活性和可靠性,在HTTP/1.1中被广泛使用,优先级高于Expires。
Cache-Control提供了更灵活和强大的缓存控制机制,而Expires则适用于简单的缓存需求。在实际应用中,推荐使用Cache-Control来控制缓存,因为它不受时钟同步问题的影响,并且提供了更多的缓存控制选项。
ETAGS和LAST-MODIFIED标头
这两个标头可以帮助浏览器确定缓存的资源自上次下载以来是否有变化。它们提供了一种有效验证缓存资源的机制,只有当内容实际发生改变时,浏览器才会下载新资源。
- ETAGS
ETags是服务器响应的一部分,给出了资源的一个唯一标识符。如果浏览器检测到ETag标头,它会在再次请求相同资源时发送这个ETag值,服务器将对此进行检查,确定资源是否更改。
- 精确的缓存验证
ETags可以提高缓存控制的精确性,因为即使文件的最后修改时间并没有变,文件内容也可能已经更新了。
- LAST-MODIFIED
Last-Modified标头告诉浏览器资源最后一次被修改的时间。如果浏览器缓存了这个资源,它会使用If-Modified-Since标头发送该时间,以询问服务器自那时以来资源是否被修改过。
- 基于时间的缓存验证
Last-Modified是一种更简单的验证方法,它通过比较日期来判断文件是否有更新。
- ETAGS和LAST-MODIFIED的关系
ETAGS和LAST-MODIFIED的区别主要在缓存验证机制、精确度、适用场景上。
ETags和Last-Modified是HTTP协议中用于缓存验证的两种机制,它们在原理、精确度和适用场景上有所不同。
1、原理和精确度
① ETags:ETag(Entity Tag)是一个实体标签,用于标示资源的唯一性。服务器根据资源内容生成一个哈希值或版本号作为ETag返回给客户端。下次请求时,客户端将ETag发送给服务器,服务器比较ETag是否变化,从而决定是否需要重新发送资源。ETag的精确度较高,任何资源的变化都会导致ETag的改变。
② Last-Modified:Last-Modified表示资源最后修改的时间戳。服务器在响应中包含Last-Modified字段,客户端在下一次请求时通过If-Modified-Since头携带这个时间戳。服务器比较时间戳,如果资源在指定时间内未被修改,则返回304状态码,表示可以使用缓存。Last-Modified的精确度较低,只能到秒。
2、适用场景
① ETags:由于其高精确度和严格的验证机制,ETags适用于需要高精度缓存控制的场景,如视频、图片等对时间敏感的资源。ETags可以减少不必要的资源传输,提高效率。
② Last-Modified:由于其较低的精确度和实现简单,Last-Modified适用于不太敏感的静态资源,如文本、HTML页面等。在资源变化不频繁的情况下,使用Last-Modified可以减少服务器的计算负担。
3、性能影响
① ETags:虽然ETags提供了更严格的缓存验证,但其计算和比较过程相对复杂,可能会增加服务器的计算负担。此外,ETags的存储和传输也会占用一定的带宽和存储空间。
② Last-Modified:由于Last-Modified只需要记录时间戳,计算和比较相对简单,对服务器负担较小。但其精度较低,可能无法准确反映资源的实际变化情况。
综上所述,ETags和Last-Modified各有优缺点,适用于不同的场景。选择合适的缓存验证机制可以提高系统的整体性能和用户体验。
二、文件版本控制
为了解决浏览器缓存过期或更新后的资源覆盖问题,开发者可使用文件版本控制的方法。这种方法确保用户能够获取到最新的文件,同时也享受缓存带来的好处。
文件指纹(HASHING)
通过给文件名加上一段Hash值,如style.dbf4e2.css,可以确保每次文件内容的改动都会产生不同的文件名。
- 文件更新立即生效
当文件改变时,Hash值也会变,这意味着文件名会变,从而用户的浏览器会请求新的文件。
重命名更新文件
与文件指纹类似,可以简单地更改文件名,例如style_v2.css,来指示资源已经更新。
- 简化的版本控制
这是一种更易于人类理解的文件版本方法,它能够明确指出资源的版本号。
三、服务工作者
服务工作者(SERVICE WORKERS)允许网站安装一个浏览器端的脚本来管理资源的捕获和缓存,这可以用来创造离线体验,或者控制资源的缓存策略。
缓存策略的控制
开发者可以编写Service Workers脚本来定义哪些资源应当被缓存、如何响应资源请求以及如何更新缓存中的资源。
- 离线体验和性能
Service Workers可以在没有网络的情况下提供页面,或者在加载新页面时使用预缓存的资源,从而提高性能。
动态缓存管理
Service Workers还允许开发者实现复杂的缓存逻辑,比如运行时缓存、按照特定的路由缓存资源等。
- 更强大的缓存能力
开发者可以根据实际需要灵活配置缓存,实现复杂的缓存策略。
总而言之,缓存JavaScript和CSS文件是一项重要的优化工作,它需要结合服务器端的配置和前端开发的策略。通过有策略地设置HTTP缓存标头、利用文件版本控制和服务工作者等先进技术,可以有效提高页面加载速度、优化用户体验。这些工作的共同目标是:使网站的静态资源尽可能长时间地存储于用户的浏览器中,同时能够在资源更新时迅速让用户获取到最新版本。
四、相关问答FAQs
1. JavaScript、CSS 文件缓存的好处有哪些?
通过缓存 JavaScript、CSS 文件,可以加速网页加载的速度,提升用户体验。缓存文件可以减少对服务器的请求次数,降低网络传输延迟,同时还可以节省带宽和服务器资源。
2. 有哪些方法可以缓存 JavaScript、CSS 文件?
可以通过设置 HTTP 响应头中的 Cache-Control、Expires 和 ETag 等字段来指定 JavaScript、CSS 文件的缓存策略。通过设置适当的缓存策略,可以让浏览器在首次请求文件后将其缓存到本地,并在下次访问同一页面时直接使用缓存文件,从而避免再次下载。
3. 如何设置 JavaScript、CSS 文件的缓存策略?
可以通过在服务器端配置相关的缓存策略来实现。对于 Apache 服务器,可以通过在 .htaccess 文件中添加以下代码来设置缓存策略:
<ifModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
</ifModule>
对于 Nginx 服务器,可以在配置文件中添加以下代码:
location ~* \.(js|css)$ {
expires 1y;
}
以上代码中的 "access plus 1 year" 和 "1y" 表示缓存的期限,可以根据实际需求进行调整。
小结:JS和CSS缓存问题
为了解决JavaScript和CSS文件的缓存问题,通常可以通过以下几种方法:
1、添加版本号:在文件链接后面添加一个版本号或时间戳,当文件内容发生变化时,版本号也随之更新,浏览器会重新加载新的文件。
<link href="styles.css?version=20230320" rel="stylesheet">
<script src="script.js?version=20230320"></script>
2、HTTP缓存头设置:通过设置合适的HTTP缓存头,如Cache-Control和Expires,可以让浏览器根据这些头的指示来决定是否需要下载新的文件。
例如,设置Cache-Control为一年:
Cache-Control: public, max-age=31536000
3、使用Service Worker:可以通过Service Worker来完全控制缓存策略,包括何时更新缓存文件。
以下是一个简单的Service Worker示例,它将缓存所有JS和CSS文件:
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
return cache.addAll([
'/styles.css',
'/script.js'
]);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
4、使用webpack等打包工具的hash:在使用打包工具时,可以利用它们的hash功能,每次构建生成的文件名都是唯一的,这样可以确保每次更新都会重新加载新的文件。
番外:HTTP缓存头共有10个,分别是:
- Expires:定义了响应的过期时间,如果当前时间小于Expires的时间,那么就可以直接使用缓存。
- Cache-Control:缓存控制字段,可以定义缓存的行为,例如no-cache表示每次都要向服务器验证缓存的有效性,no-store表示不缓存响应,max-age定义了缓存的最大有效时间。
- Last-Modified:服务器在响应中发送资源最后修改的时间。
- If-Modified-Since:客户端在下次请求时发送资源最近修改时间,如果资源没有修改,服务器会返回304状态码,表示可以使用缓存。
- ETag:服务器为每个资源生成的一个唯一标识符。
- If-None-Match:客户端在下次请求时发送缓存资源的标识符,如果ETag没有变化,服务器会返回304状态码,表示可以使用缓存。
- Connection:逐跳首部,连接的管理,例如keep-alive表示持久连接。
- Date:创建报文的日期时间。
- Pragma:报文指令。
- Trailer:报文尾部首部一览。
这些HTTP缓存头可以组合使用,以实现复杂的缓存策略。例如,Expires和Cache-Control可以共同控制缓存的过期时间,而Last-Modified和If-Modified-Since、ETag和If-None-Match则用于验证缓存的有效性
以上是缓存控制的常见策略,具体实施时需要根据项目需求和服务器配置选择合适的方法。
● 参考资料 ●
—— 深入理解浏览器的缓存机制之协商缓存与强缓存-儒雅烤地瓜的优快云博客 ——
HTTP协议中的Expires头部和Cache-Control: max-age指令有啥区别 - 优快云博客
浅析前端缓存:强缓存(Expires与Cache-Control详解)与协商缓存(4个配置) - 博客园
Expires、Cache-Control、Last-Modified和Etag总结_expires和cache-control-优快云博客
关于HTTP缓存验证Last-Modified和Etag的使用-优快云博客 | ETag和Last-modified -优快云博客

439

被折叠的 条评论
为什么被折叠?



