意外之惊喜!浏览器缓存优化方案,让页面加载速度飙升48.5%!

简介: 经过对浏览器缓存优化方案的调研和实现过程,我发现了一个令人意外的发现:**页面加载速度提升了整整48.5%!** 这个令人震撼的结果在微前端架构项目中具有重要意义,同时虽然本文是针对微前端架构的,但这个浏览器缓存优化方案同样适用于其他前端项目。本文将深入探讨这个优化方案,并分享调试和改进的经验。

前言

1688698565746.jpg

在互联网时代,页面加载速度对于用户体验至关重要。特别是在微前端架构下,更快的性能和加载速度是我们不懈追求的目标。正因如此,浏览器缓存优化方案成为了备受关注的话题。

经过对浏览器缓存优化方案的调研和实现过程,我发现了一个令人意外的发现:页面加载速度提升了整整48.5%! 这个令人震撼的结果在微前端架构项目中具有重要意义,同时虽然本文是针对微前端架构的,但这个浏览器缓存优化方案同样适用于其他前端项目。本文将深入探讨这个优化方案,并分享调试和改进的经验。

为了帮助读者更好地理解这个优化方案,我为本文准备了详尽的目录。然而,我也理解文章篇幅可能较长。因此,如果你希望直接获取核心的优化方案并应用到你的项目中,或者时间有限,我建议你直接阅读“浏览器缓存优化方案实现”和“实现的效果”两个段落。其中包含了具体的实施步骤以及令人惊喜的优化效果。

背景

在微前端架构下,前端应用被拆分成多个小应用,每个小应用都可以独立开发、构建、部署和运行,它们可以以独立的方式进行组装和集成。这种架构的优势在于可以加速开发和交付速度,提高代码的可维护性和可扩展性。但同时也会带来一些新的共性问题,例如本文描述的浏览器缓存优化等。

image.png

上述场景,典型且常见。需要清除浏览器缓存(或使用无痕模式)才能看到最新的内容,用户体验极差。本篇技术文章将重点讨论微前端项目下的浏览器缓存优化。

调研分析过程

1.分析项目微前端架构下的缓存问题

微前端中各个应用项目都是独立的,因此它们的资源(如JS、CSS和图片等)也是独立的。但是它们也有一个共同点:静态资源都在同一个域名(或几个相同的域名)下,不同的是各资源路径不同。因此设想一下我们是否可以利用这个共同点特性,尝试通过增加一个公共配置,就可以实现浏览器缓存优化的目的。

我在第三方云(简称它为 A 云)的对象存储,上传了 demo 静态资源。然后按照 A 云提供的资源 URL 在浏览器上测试,通过几次上传新的文件测试,发现每次刷新浏览器都会请求拿到最新的资源。

但为什么团队项目的却每次拿不到最新的静态资源呢? 分析后,我发现自己上传的资源是通过 A 云平台直接上传的,而团队项目的资源文件是通过公司内部上传到云上的,团队上传这个过程中涉及到公司自己的服务器或其他不确定因素

image.png

为了解决这个问题,我咨询了后端老师和 SRE 老师,但是没有得到期望的结果。我开始自己尝试在 A 云平台上处理好这个缓存优化的问题,因为这样就可以满足无论微前端有多少子应用项目,子应用项目各自又有多少静态资源,只需要在第三方云的对象存储上配置即可。这是最优的解决方案,这种可视化操作配置,简单明了、快捷,而且还安全系数高。

  1. 尝试一:

在云上的存储桶的demo上设置资源的 HTTP 头(如下图)。但随着新文件内容的上传覆盖,HTTP 头配置也会消失,因此这个方法行不通。

image.png

  1. 尝试二:

对象存储上传 SDK 文档中找到了一种解决方法,SDK 中提供了设置 HTTP 头的功能

image.png

但是由于公司对上传到存储桶进行了统一封装,如果只是为了缓存优化而改动核心代码,这并不值得。如果出现问题,那么所有团队都不能使用。自己重新再写一套上传存储桶代码也可以,但是需要跨团队协调,成本大,因此,我暂时放弃了这个方案。

接着,我继续分析自己 demo 资源和团队资源。唉!!!我发现了某些不同,沿着不同点分析,最终实现了浏览器缓存优化,而这首先就涉及到了浏览器缓存的机制

2.探讨浏览器缓存的机制

浏览器缓存是指将资源保存在浏览器本地,以便在下次访问相同资源时可以直接从本地获取,而不必重新下载和解析。

浏览器缓存的方式包括强缓存协商缓存两种:

  1. 强缓存:在一定时间内,直接从本地缓存中获取资源,而不必向服务器发送请求。可以通过设置 HTTP 响应头中的 Expires 和 Cache-Control 字段来控制是否缓存、缓存时间等。
  2. 协商缓存:在强缓存失效后,向服务器发送请求,服务端通过比较资源的 Etag 或者 Last-Modified 等字段来确定是否需要重新下载和解析资源。

为了合理利用浏览器缓存机制实现资源缓存,服务端会在 Response Header 中添加缓存标识(如协商缓存的 Etag)。我发现自己上传的 demo 资源文件存在 Etag 和 Last-Modified,而团队的资源文件只有 Last-Modified,却没有 Etag。同时,我也对比了其他项目的资源文件,发现其他项目是存在 Etag 的。

image.png

通过与后端老师和 SRE 老师沟通这个现象得知,存在 Etag 缓存标识的资源文件是存储在另一个第三方云平台上的(简称为 T 云)。到这里就该考虑静态资源迁移到 T 云的问题了,但是我一考虑到迁移成本大,而且治标不治本。而且 PM 老师给了我一个有价值的信息,某个存在 Etag 项目版本发布后,也没有更新。

此时我也发现了自身的问题,在调研过程中过于纠结 Etag 的消失,却忽略了它的兼容性问题和实际效果。总之,由于无法通过改变云平台的配置来实现缓存优化,只好自力更生,寻找其他解决办法。

3.研究微前端下的缓存优化技术

结合上面发现的问题和浏览器机制,我打算从四个方面入手。

3.1 资源的版本号或者hash值

在微前端架构下,每个小应用单独升级、独立部署带来了资源版本不一致的问题背景下,导致页面无法及时更新、加载速度和性能也有所下降。为了解决这个问题,可以通过管理资源的版本号,在每次升级时更新资源版本号,以确保资源的唯一性和正确性。

例如,可以将样式表的 URL 修改版本号为:

<link rel="stylesheet" href="style.css?v=1.0">

当样式表的内容发生变化时,只需要将 URL 中的版本号修改为 2.0,浏览器就会认为是一个新的文件,重新下载并缓存。但相比于版本号,更推荐使用 Hash

前端构建工具(如 Webpack、Rollup、Parcel 等),具备自动化构建、打包和优化前端资源功能,多数构建工具已经默认配置了 Hash。例如,使用webpack在打包时,生成的 js/css 文件名就包含 Hash 值。

当文件内容发生改变时,Hash 值也会发生改变,浏览器会重新加载最新的文件,从而保证缓存的更新。

image.png

需要注意的是,需要综合考虑多个方面的因素,如资源的大小、资源的更新频率、用户的使用习惯等,选择合适的策略(如分包)才能达到最优的效果。

但是,还不能解决 html 文件的缓存问题。因为客户端在访问页面时,浏览器加载 html 是不会带上所谓的 Hash 或者版本号的。

3.2 服务端资源URL代理

微前端中,由于每个应用都是独立部署的,应用之间的资源可能存在跨域访问的问题。为了解决这个问题,可以通过域名代理来实现资源的同源访问,从而避免跨域访问的问题。那么我们是否也可以通过代理实现浏览器缓存优化呢? 答案是可以的。

具体实现方式为,在服务器端配置一个代理服务器(有的可能叫网关),所有应用项目的资源请求都通过该代理服务器转发,代理服务器再将资源请求转发到真实的服务器上,并返回响应结果给客户端。在这个过程中,我们可以通过在下游修改响应头等方式来实现缓存策略的控制,例如增加 Cache-Control 或 Expires 字段,从而控制浏览器缓存的策略。

需要注意的是,在使用服务端资源URL代理时,要确保代理服务器的性能和稳定性,以免成为整个系统的瓶颈和单点故障。

综上所述,服务端资源域名代理是微前端架构下优化浏览器缓存的一种有效手段,能够解决跨域访问的问题,并且也可以通过控制响应头等方式来实现缓存策略的控制。

nginx 是一款轻量级的 Web 服务器。其特点是占有内存少,并发能力强。使用 nginx 可以同时实现动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...

image.png

原本客户端是直接请求服务器,由服务器直接完成请求处理工作,但加入 nginx 后,所有的请求会先经过 nginx,再由其进行分发到具体的服务器处理,处理完成后再返回到 nginx,最后由 nginx 将最终的响应结果返回给客户端。

通过配置 nginx 统一管理代理到服务器指定的根目录 html 文件,并对静态资源根目录 html 文件添加缓存配置,可以提高资源文件的获取速度。通过测试数据发现,当更新新资源时,使用 nginx 代理可以减少大约 48.5% 的时间,还可以显著降低服务器的负载,提高了网站的性能和用户体验。

此外使用 nginx 代理还有其他好处,如常见的压缩跨域等,后续如果出现迁移服务器静态资源,不用每次都更改各个项目代码中静态资源路径,只更改 nginx 代理配置即可,省时省力又风险性小。

但需要注意,html 的缓存配置一定要禁止 CDN 缓存,避免更新静态资源文件时出现缓存问题。

但是如何配置代理呢,这就需要我们深入理解并使用好浏览器缓存机制。

3.3 使用好浏览器缓存机制

我们通过上面2.探讨浏览器缓存的机制简单了解了浏览器缓存的基本原理,接下来我们需要更深入理解浏览器缓存机制,以优化缓存策略。

image.png

  1. 强制缓存

浏览器会优先从强制缓存中获取资源,如果缓存未过期,则直接使用缓存,不会发送请求。强制缓存的实现需要使用 HTTP 响应头中的 Cache-Control 和 Expires 字段。

Cache-Control 是 HTTP/1.1 中用于控制缓存的字段,常见的取值有 max-age 和 no-cache。max-age 指定资源的缓存时间,单位为秒,no-cache 指示浏览器每次请求都要向服务器确认资源是否更新。

Expires 是 HTTP/1.0 中用于控制缓存的字段,它指定资源的过期时间,但是由于存在时间戳偏差等问题,现在已经不再被广泛使用。

  1. 协商缓存

当强制缓存失效时,浏览器会发送请求到服务器,通过协商缓存来判断是否需要更新资源。协商缓存的实现需要使用 HTTP 响应头中的 ETag 和 Last-Modified 字段。

如果服务器支持 ETag 和 If-None-Match,则浏览器会在请求(Request header)中发送 If-None-Match 头部字段,携带上次请求时服务器返回(Reponse Header)的 ETag 值。服务器通过比较 ETag 值来判断资源是否更新,如果资源未更新,则返回 304 Not Modified 响应,浏览器直接使用缓存。

如果服务器不支持 ETag,则浏览器会在请求中发送 If-Modified-Since 头部字段,携带上次请求时服务器返回的 Last-Modified 值。服务器通过比较 Last-Modified 值来判断资源是否更新,如果资源未更新,则返回 304 Not Modified 响应,浏览器直接使用缓存。

注意:协商缓存的精度较低,如果资源更新了但是内容未改变,则协商缓存也会命中,因此需要慎重使用。

3.4 CDN缓存

CDN 是一种在全球范围内部署的高效、分布式网络架构,它能够为用户提供快速、可靠的内容交付服务。

image.png

当用户输入网站域名时,浏览器会向 DNS 服务器发送请求来获取该域名对应的 IP 地址。如果该域名已经被配置为 CDN,DNS 服务器将返回最近的 CDN 节点的 IP 地址。浏览器再将请求发送到所返回的 CDN 节点,而不是直接发送到网站的源服务器。如果该 CDN 节点缓存了请求的资源,CDN 节点会直接向用户返回缓存的资源,从而加快响应时间。如果 CDN 节点没有缓存请求的资源,CDN 节点会向源站服务器请求资源。当源站服务器返回资源后,CDN 节点会缓存这些资源并返回给用户。

在前端开发中,使用 CDN 缓存静态资源可以带来很多好处:

  1. 提高网站的访问速度。静态资源包括图片、脚本、样式等,它们在网站中占据了大量的带宽和存储空间。当用户访问网站时,浏览器需要下载这些静态资源,而 CDN 缓存可以将这些静态资源缓存在 CDN 节点上,使用户能够更快速地获取所需资源,从而提高网站的访问速度。

  2. 减轻服务器负载。如果所有的静态资源都由服务器提供,服务器将需要处理大量的请求,这将导致服务器负载过高,从而导致网站响应变慢或者崩溃。CDN 缓存可以将这些请求转移到 CDN 节点上,从而减轻服务器的负载,提高网站的稳定性和可靠性。

  3. 减少带宽费用。由于 CDN 节点可以在全球范围内分布,它们可以更有效地处理请求,并且可以通过缓存静态资源来减少带宽使用量,从而降低网站的带宽费用。

  4. 改善用户体验。CDN 缓存可以提高网站的访问速度,这可以改善用户的体验。

下面我们就来说下浏览器缓存优化方案具体实现步骤。

浏览器缓存优化方案实现

主要从打包构建优化缓存策略这两方面实现。以下缓存优化方案详细实现过程:

1. 打包构建(前提条件

在打包构建时,为静态资源文件添加 Hash,以便在文件内容变化时,可以强制浏览器重新加载新的文件,避免用户访问旧版本的文件,从而提高网站的访问速度。

多数构建工具已经默认配置了 Hash。其原理在于,只要文件内容不变,文件名就不会变,这样大大提高了静态文件缓存的使用寿命。但是问题也就出现了,使用 Hash 对其他资源文件(如 .js.png等)是没问题的,但是对 html 却不行。

image.png

因为客户端在访问页面时,浏览器加载 html 是不会带上所谓的 Hash的。这就导致了很多时候服务端资源文件更新了,但是客户端由于缓存,还在使用之前 html 文件加载的静态资源。

我也想过对 html 进行 Hash 处理,但是现在很多都是通过域名代理(例如 nginx),代理到云上指定的根目录 index.html。我不可能每次发个版本,就对 nginx 做一次更改,风险系数太高,所以放弃了这种想法。

所以接下来我们要解决 index.html 的缓存。解决的方法有多种。一种比较简单的方法是,在服务器端设置缓存策略,将静态资源文件的缓存时间设置为较短的时间,例如 1 天或几个小时,这样就可以保证客户端能够及时获取最新的资源文件。配置结果如下:

image.png

但是我使用的是不缓存 html方法,原因我们接着往下看。

2. 缓存策略(很重要

使用缓存策略中的强缓存协商缓存,当服务端文件更新后,浏览器借用 Header 标识来实现加载新资源。但是我不想麻烦服务端伙伴,我想先通过前端设置 html 的 Cache-Control 响应头来实现。

<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Cache-Control" content="no-cache" />

然而,需要注意的是,这个方案可能会被服务端默认配置所覆盖。如果服务器配置了 Cache-Control 响应头,将会覆盖前端设置的响应头。如果同时存在多个 Cache-Control 响应头,则最后一个响应头将覆盖前面的所有响应头。因此,如果服务器在响应中设置了 Cache-Control 响应头,则客户端和代理将根据服务器的指示进行缓存处理,而不是根据前端设置的 Cache-Control 响应头。

因此,为了确保前端设置的缓存策略生效,我们需要在服务端配置中对缓存策略进行设置。如果服务端已经配置了缓存策略,则我们需要在服务端进行相应的修改,以确保前端设置的缓存策略可以生效。

最开始首先我想到的是:借助协商缓存Etag特性,每次新资源上传,服务端更新会生成新的 Etag。利用浏览器缓存机制,每次更新资源后,刷新浏览器与服务器通信后,服务器会对比Etag的不同,从而返回200的新资源。

如果可行,这将是最合适的方式,因为只有资源更新上传后,刷新浏览器才会更新资源。

image.png

而且我还做了 demo 测试,发现可行。但是请大家注意,我做的 demo 测试没有经过任何服务器,是直接访问云上给出的 URL。我带着这次 demo 方案的可行性调试结果对 PM 产品详细阐述后,但是就像上面我说的,PM 老师给了我一个很重要的用户反馈“具备 Etag 的项目新发版后,用户浏览器刷新后也没有更新”。

此时我才反应过来,强缓存和协商缓存是 HTTP 协议中的两种不同的缓存机制,它们的具体实现方式可能因浏览器和服务器的不同而有所差异,而且协商缓存的精度较低,如果资源更新了但是内容未改变,则协商缓存也会命中

因此,需要综合考虑,选择最适合、最稳妥项目的方案。于是我想到直接给 html 设置不缓存。(当 html 中资源路径发生变化时,才会去加载新的静态资源,而其他时候调用的都是本地缓存)

image.png

通过上述方案的使用,可以有效解决浏览器缓存资源带来的问题,确保用户访问的始终都是最新资源,也可以很好的利用浏览器缓存,在没有资源更新时,快速响应页面。

有伙伴在这里提出疑问:不缓存 html,这不是每次刷新都会请求 html,这样页面效果会好吗?在下面实现的效果中,会给出答案。

我们先看下如何设置 html 不缓存。

3. 部署nginx代理配置(简单有效

在服务端 nginx 中添加禁止缓存的 Header 配置。切记,只对 html 设置禁止缓存,同时不允许 CDN 等对其缓存,配置如下:

location / {
   
    
    if ({
   
   mathJaxContainer[0]}) {
   
   
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }
}

但是,在和组内前端老师沟通方案的可行性时,发现了一个问题:我们的项目使用微前端技术搭建,许多项目资源都在同一域名下,只是路径不同。如果按照之前的方式直接在 location 中添加 Header 缓存控制配置,所有该域名下的 html 都将被禁止缓存。

为了避免这个问题,所以我对路径进行了正则处理:

location ~ ^/static/(admin1|admin2|admin3)/ {
   
    
    if ({
   
   mathJaxContainer[1]}) {
   
   
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }
}

admin1|admin2|admin3 是各应用项目路径,可以添加和修改。

在上面的配置中,我使用了以下响应头:

  • private 只能被终端用户的浏览器缓存,不允许 CDN 等对其缓存。这个会影响到 CDN 缓存命中率,但在代码量较小的情况下,可以禁用。

  • no-cache 需要进行协商缓存,发送请求到服务器确认是否使用缓存。或者可以使用 max-age=0

  • no-store 完全禁用缓存。

  • must-revalidateno-cache 类似,强制到服务端验证,适用于一些特殊场景,例如发送了校验请求,但发送失败了之类。

  • proxy-revalidate 与上面类似,要求代理缓存服务验证有效性。

添加成功后,刷新浏览器效果如下:

image.png

到此为止,我已经成功地解决了我的项目中的浏览器缓存优化问题。

需要注意的是,配置完成后,页面第一次刷新后还是旧代码,这是正常情况(因为浏览器仍在使用之前的缓存),清除缓存然后重新刷新即可。

我按照上面配置,多次测试发现可行,目前为止没有发现问题。如果大家觉得还不稳妥,还可以通过添加 ExpiresCache-Control 等响应头,控制浏览器缓存。配置完成后的效果如下:
image.png

4. 配置CDN域名缓存(锦上添花

如果说 nginx 代理解决了浏览器缓存优化,提高了资源文件的获取速度,那么 CDN 缓存无疑是在它的基础上进行了锦上添花。因为 CDN 可以通过在全球范围内分布的节点来加速内容传输和交付。所以配置 CDN 域名缓存,可以更快地响应用户请求,同时降低服务器负载。

首先需要选择合适的 CDN 服务提供商(如Cloudflare、Tencent Cloud CDN等),创建 CDN 域名并将其绑定到网站上,配置 CDN 域名缓存规则,缓存规则决定哪些资源应该被缓存以及缓存的时间。可以将缓存时间设置为几个小时或几天,或者取决于你的网站的更新频率。

image.png

查看响应头信息中的 x-cache 字段。显示为 MISS,说明没有命中 CDN 缓存,是回源的。显示 HIT,则是命中了 CDN 缓存。

实现的效果

通过浏览器缓存优化方案实现,能够有效地减少页面加载时间和资源请求压力,提高网站的整体性能。下面这个表格展示的是用户需要查看网站最新内容时,使用浏览器缓存优化前后的测试项目对比。具体数据如下:

真实数据对比

优化前:

image.png

优化后:

image.png

  • DOMContentLoaded: DOM 树构建完成。即 HTML 页面由上向下解析 HTML 结构到末尾的封闭标签</html>
  • Load: 页面加载完毕。DOM 树构建完成后,继续加载 html/css 中的 img、icon 等外部资源,加载完成后视为页面加载完毕。
  • Finish: 页面上所有 http 请求发送到响应完成的时间。http1.0/1.1 协议规定,单个域名的请求并发量是6个,即 Finish 是所有 http 请求在并发量为 6 的限制下完成的时间。

DOMContentLoaded 会比 Load 时间小,两者时间差大致等于 img、icon 等外部资源加载的时间。

Finish 的时间比 Load 大,意味着页面有相当部分的请求量。Finish 的时间比 Load 小,意味着页面请求量很少,如果页面只有一个 html 文档请求的静态页面,Finish 时间基本等于 html 文档请求的时间。

从上两图对比可以看出,见下表:

测试项目 未使用缓存优化 使用缓存优化
更新操作 清除浏览器缓存,再刷新浏览器 直接刷新浏览器
拉取资源类别 请求所有的静态资源 请求 html 和 Hash 发生改变的静态资源
拉取资源数量 16 7
页面加载完毕时间 1.37s 706ms

综上所述,可以发现:

  • 使用缓存优化后,用户更新操作更加简捷、及时;
  • 请求服务端的资源数量也下降了56%,而且静态资源数量越多,越利好;
  • 页面加载完毕时间上,使用缓存优化提速了48.5%;

其中使用 Hash 静态资源文件可以解决浏览器缓存的问题,提高资源的利用率和用户体验。配置代理服务器对静态资源文件进行缓存配置可以减少网络传输时间,进一步提高访问速度。CDN 缓存可以有效地减少服务器负载和网络传输消耗,进一步提高加载速度、提高用户体验。

但是由于清除浏览器缓存去更新资源,在实际中会很少用到。而每次刷新页面都会重新请求 html,有的伙伴可能会觉得这样不好,导致页面加载完毕时间变长。

其实在实际中,前端 Web 网站大都是单页面应用,都是通过前端路由来控制页面跳转的,很少会去刷新页面。而且由于微前端的预加载功能,当前子应用加载完毕后,才再去预加载其他子应用,每次切换应用时,该应用若已经加载过,则不会重新请求加载。所以最终结果来说,这个方案是最合适的、最稳妥的。

试验

但是我也挺好奇的,如果用户就是不管有没有缓存,是不是要更新资源,就是爱刷新浏览器。那么使用这个缓存优化方案,效果又是怎么样的呢。

所以我又做了一个试验对比。下面这两个数据截图,都是未清除缓存,直接刷新浏览器

缓存优化前:

image.png

缓存优化后:

image.png

测试项目 未使用缓存优化 使用缓存优化
更新操作 直接刷新浏览器 直接刷新浏览器
拉取资源类别 请求 html 和 Hash 发生改变的静态资源
拉取资源数量 0 4
拉取资源时间 7ms 521ms
页面加载完毕时间 455ms 451ms

通过对比不难发现,未使用缓存优化请求资源,因为都是从浏览器中获取的,所以读取时间只有 7ms,但是使用缓存优化,由于是从服务器拉去,所以4个资源总共耗时521ms。

但是令人奇怪的是,无论是否使用缓存优化,页面加载完毕时间却是惊人的近乎相同。而且通过肉眼判断,页面最终展示的时间也差不多。

首先这个不是因为Load页面加载完毕时间不准确,也不是浏览器其他的问题。而是这4个文件是异步加载的,不是 1+1 等于 2 这样来算!!!我们的标准还是Load的时间,因为Load才是最体现页面加载完成的时间,是给用户最直观展示页面完成的时间。

更何况本篇缓存优化方案的还有其他优势(资源更新的及时性、资源加载速度快、资源加载时间短。。。)

未来持续优化方向(展望未来)

本篇文章介绍了微前端架构下的浏览器缓存优化方案,其中优势之一就是提高网站的访问速度,但在网站提速方面未来还是有我们优化的空间的。比如说在浏览器缓存优化方案下,如何快速首屏渲染,如何减少加载资源的时间等。接下来我们说下提高网站的访问速度未来还能从几个方面入手:

1. 资源压缩

使用gzip压缩功能可以将网站的资源进行压缩,从而减少文件的大小,加快文件的下载速度,提高网站的访问速度。

切记,gzip 不仅构建打包工具需要配置,nginx 也需要配置。 nginx 通过在 http 块中添加以下配置实现:

http {
   
   
    gzip on; # 开启gzip压缩
    gzip_min_length 1k; # 设置gzip压缩的最小文件大小
    gzip_buffers 16 8k; # 设置gzip压缩的缓存区大小
    gzip_http_version 1.0; # 设置gzip压缩使用的HTTP协议版本
    gzip_types text/plain text/css application/json application/javascript application/xml; # 设置需要gzip压缩的文件类型
}
  • 配置gzip压缩的文件类型,通过在gzip_types中添加需要进行gzip压缩的文件类型即可,例如上面的配置中,text/plain、text/css、application/json、application/javascript和application/xml这些文件类型会进行gzip压缩。
  • 配置gzip压缩的缓存区大小和最小文件大小,通过在gzip_buffers和gzip_min_length中设置缓存区大小和最小文件大小来控制gzip压缩的性能和效果。
  • 配置gzip压缩使用的HTTP协议版本,通过在gzip_http_version中设置gzip压缩使用的HTTP协议版本来控制gzip压缩的兼容性和稳定性。

配置成功如下:

image.png

2. 分块缓存

分块进行缓存,可以减少文件的加载时间,提高页面的响应速度。

将一些不经常更新的文件与经常更新的文件分开打包。对于大型的 JavaScript 和 CSS 文件,将它们分为多个小文件打包,提高加载速度。分片的大小和数量需要根据实际情况进行调整。

image.png

3. 懒加载

根据页面需要的模块进行懒加载,减少不必要的资源加载,提高页面加载速度。可以使用 Webpack 提供的懒加载功能,或者使用动态 import 方式进行模块的懒加载。

4. 预加载

根据用户的行为预加载相关模块,提高页面的响应速度。可以使用 Webpack 提供的预加载功能,或者使用 link 标签的 prefetch 属性进行模块的预加载。

5. 数据缓存

使用本地存储、内存缓存或者服务端缓存等方式,减少重复请求数据。可以设置缓存的过期时间,当缓存过期时再次请求数据更新缓存。

6. Service Worker

具备 Service Worker 能力的浏览器对静态资源进行缓存处理。研究后发现2种实现能应用:

  1. 拦截请求,先加载本地缓存到浏览器,再请求服务器资源更新到缓存中。等页面下次刷新时,就会从本地缓存中读取到上次拉取服务端资源,然后 Service Worker 再读取服务端资源到本地缓存,这样形成了一个循环。但是这个保证不了每次刷新页面,读取到的都是新资源,需要刷新 2 次浏览器才可以。
  2. 拦截请求,直接加载服务端资源,当拉去服务端资源出现问题时,再读取本地缓存到页面中。

应用 1 是保证了加载速度,但是需要刷新 2 次浏览器才能加载到新资源,而且通过我在上面的试验数据,加载时间并不会很长,所以这个用处不大。但是我们也无法保证用户的网络环境是否稳定,所以这个也给视业务场景情况而定。

应用 2 可以加到本篇缓存优化中,做一个资源加载失败备选方案。

结尾

希望本文对您有所帮助。如果您对本文有任何疑问、建议或意见,欢迎在评论区留言。

目录
相关文章
|
4天前
|
缓存 监控 前端开发
基于时间缓存优化浏览器轮询阻塞问题
基于时间缓存优化浏览器轮询阻塞问题
16 0
|
6天前
|
缓存 NoSQL Java
SpringBoot实现缓存预热的几种常用方案
SpringBoot实现缓存预热的几种常用方案
|
2月前
|
存储 缓存 算法
【C/C++ 性能优化】提高C++程序的缓存命中率以优化性能
【C/C++ 性能优化】提高C++程序的缓存命中率以优化性能
120 0
|
3月前
|
存储 缓存 UED
缓存策略与Apollo:优化网络请求性能
缓存策略与Apollo:优化网络请求性能
|
5月前
|
缓存 NoSQL Java
聊聊分布式应用中的缓存方案(一)
聊聊分布式应用中的缓存方案(一)
40 0
|
27天前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
3月前
|
缓存 Java 数据库
优化您的Spring应用程序:缓存注解的精要指南
优化您的Spring应用程序:缓存注解的精要指南
47 0
|
1天前
|
存储 缓存 前端开发
【Flutter前端技术开发专栏】Flutter中的图片加载与缓存优化
【4月更文挑战第30天】本文探讨了 Flutter 中如何优化图片加载与缓存,以提升移动应用性能。通过使用图片占位符、压缩裁剪、缓存策略(如`cached_network_image`插件)以及异步加载和预加载图片,可以显著加快加载速度。此外,利用`FadeInImage`、`FutureBuilder`和图片库等工具,能进一步改善用户体验。优化图片处理是提升Flutter应用效率的关键,本文为开发者提供了实用指导。
【Flutter前端技术开发专栏】Flutter中的图片加载与缓存优化
|
6天前
|
SQL 缓存 数据库
在Python Web开发过程中:数据库与缓存,如何使用ORM(例如Django ORM)执行查询并优化查询性能?
在Python Web开发中,使用ORM如Django ORM能简化数据库操作。为了优化查询性能,可以:选择合适索引,避免N+1查询(利用`select_related`和`prefetch_related`),批量读取数据(`iterator()`),使用缓存,分页查询,适时使用原生SQL,优化数据库配置,定期优化数据库并监控性能。这些策略能提升响应速度和用户体验。
8 0
|
18天前
|
存储 缓存 自动驾驶
缓存策略与Apollo:优化网络请求性能
缓存策略与Apollo:优化网络请求性能