本文发布于微信公众号码上花甲,每天 9: 00 准时为你推送高质量前端开发相关文章!更有精品资源供你免费获取!欢迎关注。
在 SPA 应用中,我们常需要对首屏做加载优化,那么,常见的 SPA 首屏优化方式有哪些呢?
结合我自己从业这几年的经验以及网络上搜集的资料,对这个问题做一次总结,如果你也在工作中有这方面的需求,不妨一起讨论一下。
我认为,首屏优化的核心是加载和解析的性能。
加载优化的核心是 资源体积 和 首屏资源数量 。
解析优化的核心是 资源体积 和 代码的执行性能 。
由此可得,资源体积会同时影响加载和解析的性能。
1. 加载优化
加载方面最有效的方式是缓存的合理使用,要知道,再快的网速和再大的并发数也不如直接跳过下载阶段。下面是一些常见的缓存策略:
1.1 浏览器缓存
我们知道,浏览器会自动缓存一些资源,比如 CSS、JS 文件和图片等。当用户再次访问同一页面时,浏览器可以直接从缓存中获取这些资源。这种方式主要通过 HTTP 的缓存控制头部字段(如 Cache-Control
、Expires
、ETag
、Last-Modified
等)来实现。比如,让浏览器将资源缓存在本地 1 小时:
// 设置 Cache-Control 头部,告诉浏览器缓存该资源 1 小时
response.setHeader('Cache-Control', 'max-age=3600');
1.2 服务端缓存
在服务端,可以将数据库查询结果、渲染后的 HTML 页面等缓存起来。当收到相同的请求时,服务端可以直接返回缓存的数据,而不需要再次进行数据库查询或页面渲染。这种方式能有效减少服务器的计算负载,提高响应速度。
对于数据库查询结果的缓存,可以使用 Redis 等缓存数据库,将查询结果存储在内存中以供快速访问。至于服务端渲染,现在有很多前端框架都可以实现,比如 React 生态中的 Next.js。
1.3 内容分发网络(CDN)缓存
CDN 是一种分布式网络,它可以在全球各地的节点上缓存网站的静态资源。当用户请求这些资源时,CDN 会将请求路由到最近的节点,从而减少网络延迟,提高加载速度。这种方式能让不同地区的人都可以享受稳定可靠的下载速度。
1.4 应用级缓存
在前端应用中,我们也可以使用各种缓存策略,如使用 localStorage 或 sessionStorage 来缓存用户的登录状态、用户的偏好设置等数据;使用 IndexedDB 或 Web SQL Database 来缓存大量的数据,如离线应用的数据等。
1.5 Service Worker 缓存
Service Worker 是运行在浏览器背后的独立线程,可以用来实现资源的缓存。通过它,我们可以自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存完全由我们控制,使得离线加载成为可能。
关于 Service Worker 的应用,之前我写了两篇相关的文章,感兴趣的话可以看看:
除了上面的缓存策略,还有一些其他方式可以优化加载性能:
- 合理分包 :在还使用 HTTP1.X 的情况下,衡量包的体积和并发数量,利用 webpack 的 Code Split 技术探索出合适的包体积和资源数量。
- 静态资源分域 :将图片,音视频等静态资源放到不同域名加载,防止加载时受浏览器并发数限制。同时还可以实现 cookie 隔离,在安全和加载速度上都有极大好处。
- DNS预解析 : 合理采用DNS预解析。
域名解析(DNS 寻址)是一个相对比较耗时的过程。
理想状态下,浏览器通过查询系统 hosts 或者进一步询问本地 DNS 服务器就可以获得结果(服务器 IP),但也很有可能要经历完整的寻址过程:分别与根 DNS 服务器、域 DNS 服务器、以及解析 DNS 服务器进行多次交互才能获得结果。
所以启用 DNS 预解析可以很大程度上节省域名寻址的时间(但凡事有度,过犹不及),如果搭配静态资源分域,会有更优秀的表现。 - 尽量启用 HTTP2:HTTP2 提供了多路复用可以突破并发限制,头部字段压缩也可以减少传输的数据体积,二进制数据传输也可以让多种数据类型选择更合适的方式传输。
2. 解析优化
解析优化分为资源体积优化以及运行时的性能优化。
2.1 资源体积优化
基本的方式有:压缩字体、图片以及音视频等静态文件体积等等。
另外,现代化的工程基本上都用了 Webpack 或其他构建工具,以 Webpack 为例,其实 Webpack 以及社区的大佬们都为我们的工程提供了很多的优化。
推荐吴浩麟的《深入浅出Weblack》,很好懂,而且有免费的电子版:http://webpack.wuhaolin.cn
举几个例子:
- 最大化的利用 Webpack 的
Scope Hositing
以及Tree Shaking
技术, 这就要求我们执行按需加载策略,并尽可能的使用ES Module
方式去组织代码和选择三方代码的入口点 ( resolve.mainFields )。 - 利用异步方式延迟加载(按需加载)非首屏资源( Dynamic Imports )。
- 其他常规的公共代码提取,资源压缩等方案。
注意:懒加载和按需加载的概念不同,前者是延迟加载,后者是不必要不加载。
2.2 运行时性能优化
这是一个复杂且繁重的工作,我们必须确保在日常开发中书写出高质量的代码,但由于开发人员的经验不同,很难保证每个人都能写出好的代码来。
所以 Code Review 环节是极其有必要的,需要经验丰富和技术水平高的工程师来指导和把关。
比如:CSS 设计和书写方式,JS 实现方式等。我上家公司有位同事在 CSS 方面就很有经验,像页面重绘规则等,跟他学到不少,非常感谢他,当时也是他把我招进去的。总之吧,这方面要多学习其他人优秀的实现方式,是一个日积月累的过程。
除了上面提到的这些优化方式,我还问了下 ChatGPT,它给的回答确实很全面:
我们仔细看一下 ChatGPT 给出的参考,其实不难发现都是我们平时工作中做的一些实现,如果平时没有梳理的习惯的话,很难一次讲出来。比如上面的路由懒加载、组件库局部引用,这些不都是我们项目中常见的优化方式吗?
建议如果你平时有时间的话,可以对自己现有的知识体系梳理一下。你可能会大吃一惊哈,因为你会发现,总感觉自己懂得不少,真正画在一张图上你就会发现自己知道的少得可怜。有很多很多细枝末节的知识、技能,我们平时如果不记录下来的话,时间久了就都忘掉了。
好了,今天就先分享这么多吧,感谢阅读,更多精彩内容见下方公众号。
3 comments
文章的确不错啊https://www.cscnn.com/
dffff|´・ω・)ノ
测试