网站开发代码实例,wordpress广告位插件哪个好,哪里购买网站空间好,网站支持ipv6怎么做前言
在过去几年#xff0c;我曾经写过几篇和性能优化相关的文章#xff0c;例如有性能优化方法相关的#xff0c;有性能监控相关的。但是都只关注于局部#xff0c;没有从整体上去看待、分析性能优化。所以本文打算尝试从整体上去分析前端性能优化#xff0c;从性能指标…前言
在过去几年我曾经写过几篇和性能优化相关的文章例如有性能优化方法相关的有性能监控相关的。但是都只关注于局部没有从整体上去看待、分析性能优化。所以本文打算尝试从整体上去分析前端性能优化从性能指标性能分析到性能优化这一整条链路来分析前端性能优化。
在做性能优化之前首先要了解如何评价性能好坏不能只凭主观感受来判断。因为每个人的感受都不一样例如首屏加载时间有人觉得 2 秒就够快了有人觉得 5 秒也不错。为了避免这种情况我们要建立一个性能评价系统在统一的标准下分析页面性能好坏。这可以通过一系列性能指标来实现例如 FCP、LCP、CLS 等性能指标。
对性能指标有一定了解后就可以开始编写 SDK 来收集性能数据了当然也可以使用开源的监控系统。一般的监控系统都会有一个监测平台用来查看性能数据。然后我们就可以分析出来页面的性能瓶颈在哪里再使用对应的性能优化方法来解决性能问题。
以上是关于如何做性能优化的方法论下面来看一下具体如何做。
性能指标
在优化性能的过程中我们需要依赖一些具体的性能指标来对页面性能进行分析。然后通过对比优化前后的性能指标我们可以准确判断性能优化的效果。对于性能指标我们一般关注以下 9 个就可以了。 FP
FP(first-paint)从页面加载开始到第一个像素绘制到屏幕上的时间。其实把 FP 理解成白屏时间也是没问题的。
FCP
FCP(first-contentful-paint)从页面加载开始到页面内容的任何部分在屏幕上完成渲染的时间。对于该指标内容指的是文本、图像包括背景图像、svg 元素或非白色的 canvas 元素。 为了提供良好的用户体验FCP 的分数应该控制在 1.8 秒以内。 LCP
LCP(largest-contentful-paint)从页面加载开始到最大文本块或图像元素在屏幕上完成渲染的时间。LCP 指标会根据页面首次开始加载的时间点来报告可视区域内可见的最大图像或文本块完成渲染的相对时间。
一个良好的 LCP 分数应该控制在 2.5 秒以内。 FCP 和 LCP 的区别是FCP 只要任意内容绘制完成就触发LCP 是最大内容渲染完成时触发。 LCP 考察的元素类型为
img元素内嵌在svg元素内的image元素video元素使用封面图像通过url())函数而非使用CSS 渐变加载的带有背景图像的元素 包含文本节点或其他行内级文本元素子元素的块级元素。 CLS CLS(layout-shift)从页面加载开始和其生命周期状态变为隐藏期间发生的所有意外布局偏移的累积分数。
布局偏移分数的计算方式如下
布局偏移分数 影响分数 * 距离分数 影响分数测量不稳定元素对两帧之间的可视区域产生的影响。 距离分数指的是任何不稳定元素在一帧中位移的最大距离水平或垂直除以可视区域的最大尺寸维度宽度或高度以较大者为准。 CLS 就是把所有布局偏移分数加起来的总和。
当一个 DOM 在两个渲染帧之间产生了位移就会触发 CLS如图所示。 上图中的矩形从左上角移动到了右边这就算是一次布局偏移。同时在 CLS 中有一个叫会话窗口的术语一个或多个快速连续发生的单次布局偏移每次偏移相隔的时间少于 1 秒且整个窗口的最大持续时长为 5 秒。 例如上图中的第二个会话窗口它里面有四次布局偏移每一次偏移之间的间隔必须少于 1 秒并且第一个偏移和最后一个偏移之间的时间不能超过 5 秒这样才能算是一次会话窗口。如果不符合这个条件就算是一个新的会话窗口。可能有人会问为什么要这样规定其实这是 chrome 团队根据大量的实验和研究得出的分析结果 Evolving the CLS metric。
CLS 一共有三种计算方式
累加取所有会话窗口的平均数取所有会话窗口中的最大值
第三种方式是目前最优的计算方式每次只取所有会话窗口的最大值用来反映页面布局偏移的最差情况。详情请看 Evolving the CLS metric。
首屏渲染时间
页面从加载开始到页面渲染完毕的时间如果有些页面的内容特别多我们可以只取当前屏幕展示的内容的加载时间作为首屏渲染时间。因为其他部分对于用户来说看不到所以可以忽略那部分的加载时间。
FPS 帧率
页面的帧率就是每秒显示多少帧一般使用 requestAnimationFrame() 来计算当前页面的 FPS。
资源加载时间
资源加载时间指的是每个静态资源文件的加载时间通过它可以找到哪些资源加载慢然后再分析原因。
缓存命中率
缓存命中率是用来分析你的缓存策略、内容分包机制做得好不好。一般缓存命中率越高说明你缓存策略、内容分包机制做得越好。
接口请求耗时
通过接口请求耗时可以分析哪些接口慢然后再找出是服务器问题或者是接口内容过大或是网络问题。
小结
通过这 9 个指标我们就可以对页面做到一个全面的、客观的分析进而知道性能瓶颈出在哪。例如资源加载时间比较慢我们可以分析出来有可能是网络问题再进而分析是不是 DNS 有问题、或者网络带宽问题、还是 CDN 有问题等等也可以看看是不是资源体积过大需要进行压缩或者拆包。
总的来说了解性能指标可以提升你对性能优化的认识帮助你更好的实现性能优化。
性能监控
通过监控我们可以拿到所需的性能指标数据。如果开发监控系统的压力过大我们可以使用开源的监控系统例如 sentry 就是一个很不错的监控平台除了能收集性能数据还能收集错误数据。不过如果不想使用这种大而全的监控平台也可以选择自己开发一个监控平台一个完整的监控平台包含了监控 SDK、数据清洗和存储、数据展示。两三个人花一两个月的时间就能开发出来一个够用的监控系统了如果对监控 SDK 有兴趣的可以看看我这篇文章 前端监控 SDK 的一些技术要点原理分析。
如果不需要持续的监控页面性能而只是想进行一次评测那我们可以使用 chrome 浏览器自带的 lighthouse 工具来进行测试。 选择你想要收集的数据和所在平台然后点击 Analyze page load 即可开始测试。 从上图可以看出几个核心的性能指标都已经有了并且还能看到整体页面和性能分数非常的简单和直观。
小结
收集性能数据的方式基本上就是两种
使用监控 SDK数据全面有难度使用测试工具能收集基本的数据使用简单
通常情况下测试工具就够用了除非你的网站需要追求极致的性能和用户体验否则不需要上监控平台。
性能优化方法
性能监控、性能指标是用来收集数据、分析性能瓶颈用的在找到性能瓶颈后就得使用对应的性能方法去优化它。我觉得要做性能优化可以从两方面入手
加载时优化页面加载速度运行时资源加载完毕后在页面开始运行的时候进行优化
所有的性能优化手段都可以归纳为以上两类。其中对性能影响最大、收益最大的是在页面加载时进行优化。 从上图可以看到一共有 23 条性能优化方法其中加载时优化有 10 条运行时优化有 13 条。由于篇幅有限这 23 条性能优化方法不能逐一展开细讲就讲讲其中的一条吧 使用 CDN。
静态资源使用 CDN
内容分发网络CDN是一组分布在多个不同地理位置的 Web 服务器。我们都知道当服务器离用户越远时延迟越高。CDN 就是为了解决这一问题在多个位置部署服务器让用户离服务器更近从而缩短请求时间。
CDN 原理
当用户访问一个网站时如果没有 CDN过程是这样的
浏览器要将域名解析为 IP 地址所以需要向本地 DNS 发出请求。本地 DNS 依次向根服务器、顶级域名服务器、权限服务器发出请求得到网站服务器的 IP 地址。本地 DNS 将 IP 地址发回给浏览器浏览器向网站服务器 IP 地址发出请求并得到资源。 如果用户访问的网站部署了 CDN过程是这样的
浏览器要将域名解析为 IP 地址所以需要向本地 DNS 发出请求。本地 DNS 依次向根服务器、顶级域名服务器、权限服务器发出请求得到全局负载均衡系统GSLB的 IP 地址。本地 DNS 再向 GSLB 发出请求GSLB 的主要功能是根据本地 DNS 的 IP 地址判断用户的位置筛选出距离用户较近的本地负载均衡系统SLB并将该 SLB 的 IP 地址作为结果返回给本地 DNS。本地 DNS 将 SLB 的 IP 地址发回给浏览器浏览器向 SLB 发出请求。SLB 根据浏览器请求的资源和地址选出最优的缓存服务器发回给浏览器。浏览器再根据 SLB 发回的地址重定向到缓存服务器。如果缓存服务器有浏览器需要的资源就将资源发回给浏览器。如果没有就向源服务器请求资源再发给浏览器并缓存在本地。 小结
由于篇幅有限文中提及的一共 23 条性能优化方法可以看我的这篇文章前端性能优化 24 条建议2020。
性能优化实战
在所有性能优化方法中收益最大的有三个压缩、懒加载和分包、缓存策略。绝大多数的应用做了这三个优化后页面性能都能得到极大的提升。
压缩
压缩包含代码压缩和文件压缩常用的代码压缩工具有 terser、uglify文件压缩一般使用 gzip。1m 的文件使用 gzip 压缩后体积一般是 300-400kb。
压缩通常情况都是在前端打包的时候做然后将打包好的文件上传到服务器。用户访问网站时nginx 先查看用户访问的资源是否有 .gz 后缀的文件gzip 压缩后的文件如果有就返回没有就自己压缩后再返回。这一块需要在 nginx 上进行配置才支持默认不开启。尽量不要让 nginx 压缩因为访问量高的时候对服务器压力很大。
压缩是对整体项目的体积大小进行优化。
懒加载和分包
路由懒加载基本上每个前端都会但是某些系统仍然需要手动优化。比如一些构建工具会默认把所有的第三方包都打在 verdor.js 文件里。但实际上并不是所有的页面都需要把所有的第三方包都加载进来所以需要做好具体的分包策略来进行优化。分包主要是为了对打包好的资源进行拆分让一些不是所有页面都要使用的资源做到懒加载。
懒加载和分包不改变项目的体积大小而是将一些不是那么重要的资源放到后面再加载。比如有 10 个页面的资源每个 1m假设加载时间为 1 秒都做成懒加载后每次访问页面只需要一秒而不是都打包在一起首次访问要 10 秒。
缓存策略
浏览器缓存分为强制缓存和协商缓存强制缓存就是缓存生效期间浏览器会直接使用缓存的资源而不会发起请求。协商缓存就是浏览器发起请求后发现文件未变化然后再使用缓存。
缓存策略就是围绕着强制缓存、协商缓存做的优化方案。在做优化之前还要给大家再介绍一下缓存命中率。
缓存命中率缓存命中的资源/所有请求的资源。缓存命中率越高说明你的缓存策略做得越好。
缓存策略一般通过 nginx 来实现当然也可以自己手写代码实现。现在常用的缓存策略是
打包文件时所有文件名称按照文件内容进行 hash 命名当内容改变时文件名也会改变在 nginx 配置 html 文件为 cache-control: no-cache每次浏览器请求 html 时都要向服务器发起请求查询 html 文件是否有变化即协商缓存其他所有静态资源文件设为长缓存例如缓存时间为一年即强制缓存
这样优化后除了首次打开页面需要加载静态资源后面再打开页面就不需要了所以能在瞬间打开页面。当项目代码更新后相关的 js、css 资源文件会发生变化其他不变的部分代码不会变化。当资源文件发生变化后html 也会发生变化引用的资源文件名称变了。然后浏览器会重新加载 html 中发生变更的资源没有变化的资源会使用缓存。目前只有 webpack 支持根据文件内容生成 hash所以说 vite 是代替不了 webpack 的它们会同时存在。
想了解如何利用 webpack 实现文件精确缓存的可以看我这篇文章webpack express 实现文件精确缓存
现在我们再看一下其他比较知名的网站是怎么做缓存的。
一些比较好例子
https://www.zhihu.com/https://bbs.hupu.com/all-nbahttps://www.google.com/
不好的例子
省略...
为了避免不必要的问题不好的示例还是不帖了但是大家可以找一些小网站或者小公司的官网看看基本上都没怎么做性能优化。
另外有些细心的同学可能会发现即使没有设置 cache-control浏览器也会进行缓存。这是因为没有设置 cache-control 响应头时浏览器将自行选择缓存策略。
浏览器默认行为即使响应头部中没有设置 Cache-Control 和 Expires浏览器仍然会缓存某些资源这是浏览器的默认行为是为了提升性能进行的优化每个浏览器的行为可能不一致有些浏览器甚至没有这样的优化。
性能优化的成本和收益
在绝大多数的单页面应用SPA中页面采用懒加载的策略并且通过打包工具实现代码压缩基本上不会有性能问题。但是随着项目规模的扩大可能会出现性能问题这时就需要做性能优化了。
但是性能优化并非无止境的进行。我们需要充分考虑优化的成本和收益而不是盲目地采用所有可能的优化方法因为这将带来过高的开发和维护成本。只有当项目的性能表现无法满足预设的性能指标时我们才需要进行进一步的优化。这样我们可以在保证项目性能的同时也能控制好优化的成本。
举例性能优化实战中说到 vite 不能实现按内容进行 hash。也可以打包时用 webpack 来替代 vite。但成本比较高没什么必要除非对性能有极端的要求。
疑难解答
不好的代码是否会影响性能优化
如果做好了项目的整体架构设计结合性能优化方法论、前端工程化、合理的研发流程、代码规范和 CodeReview不好的代码对性能影响很小除非写一些死循环代码。当然前端工程化这些概念非常宽泛也不好理解有兴趣可以看我写的这一本电子书带你入门前端工程
举例一个页面几千行代码会不会影响页面性能。如果这个页面确实需要这些代码那说明代码总量不会变再怎么拆分还是那么多代码。所有代码写在一个页面只会影响代码可读性而不会影响性能。
总结
关于性能优化的内容已经说完了但是我还想说点别的主要想说一下我们应该学习哪些技术才能让它更加保值。
在我看来越偏向于业务的技术越不容易过时为什么呢需求在变技术一直在变业务也一直在迭代。前端技术的发展非常快也涌现出很多的框架例如 HTML4 到 HTML5 的升级或者从jQuery 到前端三大框架的转变但是总归就是两个字效率。
作为开发者我们需要保持好奇心和学习热情不断探索新的技术只有这样我们才能在这个快速发展的时代中立于不败之地。介绍一款程序员都应该知道的软件JNPF快速开发平台很多人都尝试用过它它是功能的集大成者任何信息化系统都可以基于它开发出来。
JNPF可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量通过图形化、可视化的界面以拖放组件的方式即可快速生成应用程序的产品大幅降低了开发企业管理类软件的难度。
当然我更建议大家成为一个全栈不要把自己的定位局限于前端。