缓存破坏的边缘情况
缓存破坏的边缘情况
原文:https://medium.com/hackernoon/an-edge-case-for-cache-busting-da09a7f2b5f5
假设我们正在设计一个高性能的网站。我们从 Steve Sounders 的书中了解到,通过关注前端优化,我们可以获得最大的性能提升。
为了开始改善性能,我们可以做以下事情:
- 连接和缩小资产。通过将所有的 JavaScript 和 CSS 压缩到一个文件中,我们减少了网络流量。下载单个较大的文件也比下载几个较小的文件更快。
- 从边缘提供内容。通过从物理上更靠近用户的服务器提供内容,我们提高了性能。我们可以使用内容交付网络(CDN)来做到这一点。
- 设置缓存和压缩头。因为这些资产不会改变,所以通常只希望用户下载一次。我们可以通过将到期头设置为遥远的未来(比如一年)来实现。此外,我们可以通过压缩它们来减小下载大小。
如今,这种架构很容易实现。像 webpack 或 gulp 这样的工具和来自 CloudFlare 或亚马逊 CloudFront 的服务将会为你处理大部分(如果不是全部)的事情。
然而,这种架构有一个已知的问题。从技术上讲,任何时候实现浏览器缓存都会遇到这个问题。让我们仔细看看这个问题和一个常见的解决方案。
破坏缓存
计算机科学只有两个硬东西:缓存失效和事物命名。
虽然这是真的,但在这种情况下,使缓存失效并不困难。由于网络的性质,我们有一个集中式缓存,而不是分布式缓存。当用户请求我们的网页时,我们有机会使缓存无效并加载新的资产。
常见的做法是对文件名进行版本控制或追加查询字符串参数。虽然您可以手动完成这项工作,但您用来连接和缩小文件的工具也可以做到这一点。我建议使用校验和散列,而不是版本号。
现在,下一次用户请求我们的 web 页面时,到资产的路径将会不同,导致它们被下载和缓存。
最大化缓存命中率
每个人都有一个计划,直到他们的嘴被打中
这个架构的主要目标是让用户只下载这些资产一次。然后,在随后的访问中,这些资产将从其本地浏览器缓存中加载,从而大大提高性能。
这个架构实现了这个目标。然而,它只是优化了悲伤的路径。这是当用户有一个空的或陈旧的缓存。这样做,我们实际上降低了快乐之路的性能。这是当用户有一个主要的缓存。
资产不经常变化或没有高流量的网站可能不会注意到这种权衡。因此,边缘案例的标题有双重含义。尽管如此,我想强调这种权衡,因为类似的文章很少这样做。
让我们在这个架构下演示一个用户流:
- 用户第一次访问网站
- 用户下载资产
- 用户再次访问网站
- 浏览器从缓存中加载资产
- 开发人员发布新资产
- 用户再次访问网站
- 用户下载资产
从表面上看,这似乎不错。用户下载了资产,并在随后的访问中使用了缓存。然后,当我们更新资产时,用户在下一次访问站点时下载了新的资产。
问题出在最后一步。用户再次下载所有资产。虽然这些资产确实是新的,但很可能只有一小部分文件发生了变化。因此,让一个用户用一个准备好的缓存再次下载所有的东西并不是最优的。
让我们以压缩的 JavaScript 文件为例。虽然定制 JavaScript 代码可能会频繁更改,但大多数非定制代码不会。这
如果我们将我们的资产分成两个文件,我们可以进一步优化这个架构,同时不会增加很多额外的请求。因此,对于 JavaScript 文件,我们将不常更改的代码压缩到一个文件中,将频繁更改的代码压缩到另一个文件中。我们可以对我们的 CSS 做同样的事情。
现在,如果我们播放相同的用户流,最后一步变成了用户仅下载 已更改的 资产。这要优化得多。尤其是高流量网站。如果我们考虑为一个每月有 100 万次点击的站点分离出 jQuery(最小化 40KB ),那就是 40GB 的节省。虽然这在现代互联网时代听起来可能不太像,但这可能是你的 CDN 计划层之间的差异。
最初发表于【jason.pureconcepts.net】。
黑客中午是黑客如何开始他们的下午。我们是 @AMI 家庭的一员。我们现在接受投稿并乐意讨论广告&赞助机会。
要了解更多信息,请阅读我们的“关于”页面、在脸书上给我们点赞/发消息,或者简单地说, tweet/DM @HackerNoon。