如何考虑性能优化

这篇文章主要介绍性能优化相关的知识点,包括CDN、懒加载、回流重绘、节流防抖等。

如何考虑性能优化

如何实现Vue项目中的性能优化

编码阶段

  • 采用 keep-alive 缓存组件
  • 使用路由懒加载、异步组件
  • 第三方模块按需导入
  • 图片懒加载
  • 防抖、节流

SEO优化

  • 预渲染
  • 服务端渲染 SSR

预渲染 是一种构建阶段生成匹配预渲染路径的HTML文件方式,来提高网站在搜索引擎中的自然排名的方法。 好处是可以改善网页的SEO,而不需要服务器端渲染,缺点是为每个预渲染的路由生成一个HTML文件,可能会增减构建时间和文件大小。

两者的区别:

  • 预渲染是在构建阶段生成静态 HTML 文件,而 SSR 是在服务器端动态编译 HTML。
  • 预渲染适合改善少数营销页面的 SEO,而 SSR 适合改善动态数据的 SEO。
  • 预渲染的优点是简单易用,不需要服务器端资源,而 SSR 的优点是可以实现更快的首屏渲染,更好的用户体验和更高的转化率。
  • 预渲染的缺点是需要为每个路由生成一个 HTML 文件,可能增加构建时间和文件大小,而 SSR 的缺点是需要更多的服务器端资源,可能增加服务器端压力和复杂度。

打包优化

  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • Tree Shaking是一种消除未使用代码的过程,确定哪些代码被引用,哪些代码没有被引用。减少最终打包的文件大小,使其更快地下载和解析。
  • Scope Hoisting是一种将多个JavaScript模块合并到一个作用域的过程,可以通过将跨模块的引用变成静态而不是动态的属性查找,提高运行时的性能
  • 使用 cdn 加载第三方模块

用户端

  • 骨架屏

    是一种在网页内容加载之前,显示网页的基本结构和样式的技术,它可以让用户感觉网页加载更快,减少用户的等待感和焦虑感。

  • PWA

    是一种使用网页技术,但可以安装和运行在所有设备上,提供类似于原生应用的体验的技术,它可以让网页更适应不同的设备和网络环境,更方便用户的访问和使用。

SPA应用如何优化首屏加载速度

  • 请求优化, 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积。CDN可以实时根据流量、节点连接、负载状况以及到用户的距离、响应时间等综合因素 将请求重新导向最合适的服务节点中。

  • 缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验

  • gzip:开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小

  • http2

    如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。

  • 使用路由懒加载, import 动态加载页面组件

  • 预渲染

  • 按需加载第三方库

  • 图片懒加载

  • 使用 svg 图标

  • 选用合适的图片格式,做图片压缩,在不影响使用的情况下压缩图片质量

CDN

CDN的概念

CDN, content delivery network,内容分发网络,又称内容传送网络。

当我们在开发网站的时候,经常会有很多的图片、视频、动态效果需要部署,这些样式的引入通常有两种方式,

一是直接放在项目内部,再部署到公网上,这样通常会严重影响网站访问速度,见我上篇文章–如何提升网站加载速度

第二种做法就是 使用CDN来加速网站里特别消耗资源的文件。那CDN到底是什么呢?

有个很形象的网上购物比喻可以帮助理解:

访问没有使用CDN的网站,就相当于在淘宝下单了一件货源在深圳的商品,不管你是从哪里下单的,河南、湖北、甘肃 or 西藏,商家都会从深圳统一发货,那么到货的时间长短不一了,一般来说时间都要三四五天的样子

访问使用了CDN的网站,就相当于在京东自营下单了一件商品。

我们都知道,京东自营的物流是很牛的,淘宝是将物流外包给了很多小公司,所以货物的中转次数很多,很复杂,但是京东搭建了属于自己的一整套物流体系,它会根据你的收货地址去找离收货地址最近的物流仓库,然后直接就近发货。比如你在甘肃下的单,西安的仓库里有你需要的货物,京东就直接从西安给你发过来了。

CDN就相当于网络资源世界里的京东仓储系统

CDN的全称是, content delivery network,内容分发网络。顾名思义,就是专门分发资源的网络。

CDN系统能够实时根据网络流量和各节点的连接、负载情况、到用户的距离和响应时间等综合信息将用户的资源请求重新导向离用户最近的服务节点上,其目的就是让用户就近取得所需内容,解决网络拥挤的问题,提高用户的访问速度。

下图就很好的说明了有无CDN时的访问情况

CDN组成

了解了CDN的作用之后,再往下继续延伸

CDN作为内容分发的服务器,就自然有两点问题,一是内容从何处来,二是它能分发给多少用户

典型的CDN系统由下面三个部分组成:

  • 分发服务系统:最基本的工作单元就是Cache设备,cache负责最终用户的访问请求,把缓存在本地的内容快速地提供给用户。同时还负责与源站点进行内容同步,把更新的内容以及本地没有的内容从源站点获取并保存在本地。Cache设备的数量、规模、总服务能力是衡量一个CDN系统服务能力的最基本的指标。
  • 负载均衡系统:主要功能是负责对所有发起服务请求的用户进行访问调度,确定提供给用户的最终实际访问地址。两级调度体系分为全局负载均衡(GSLB)和本地负载均衡(SLB)。全局负载均衡主要根据用户就近性原则,通过对每个服务节点进行“最优”判断,确定向用户提供服务的cache的物理位置。本地负载均衡主要负责节点内部的设备负载均衡
  • 运营管理系统:运营管理系统分为运营管理和网络管理子系统,负责处理业务层面的与外界系统交互所必须的收集、整理、交付工作,包含客户管理、产品管理、计费管理、统计分析等功能。

CDN工作原理

用户未使用CDN缓存资源的过程:

  1. 浏览器通过DNS对域名进行解析(DNS解析过程),依次得到此域名对应的IP地址
  2. 浏览器根据得到的IP地址,向域名的服务主机发送数据请求
  3. 服务器向浏览器返回响应数据

用户使用CDN缓存资源的过程:

  1. 对于点击的URL,经过本地DNS系统的解析,发现该URL对应的是一个CDN专用的DNS服务器,DNS系统就会将域名解析权交给CNAME指向的CDN专用的DNS服务器。
  2. CND专用DNS服务器将CND的全局负载均衡设备IP地址返回给用户,用户向CDN的全局负载均衡设备发起数据请求
  3. CDN的全局负载均衡设备根据用户的IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求
  4. 区域负载均衡设备选择一台合适的缓存服务器来提供服务,将该缓存服务器的IP地址返回给全局负载均衡设备
  5. 全局负载均衡设备把服务器的IP地址返回给用户,用户向该缓存服务器发起请求,缓存服务器响应用户的请求,将用户所需内容发送至用户终端。

用户使用CDN缓存资源的过程

CDN的好处

除了加速的网站访问速度,CDN还有什么好处呢

  1. 有利于搜索排名。换位想想,你愿意去访问一个加载特别慢的网站吗,你如果不愿意,那么这些搜索引擎自然就不会把你放在结果排名的前面
  2. 减少托管成本。

(1)在性能方面,引入CDN的作用在于:

  • 用户收到的内容来自最近的数据中心,延迟更低,内容加载更快
  • 部分资源请求分配给了CDN,减少了服务器的负载

(2)在安全方面,CDN有助于防御DDoS、MITM等网络攻击:

  • 针对DDoS:通过监控分析异常流量,限制其请求频率
  • 针对MITM:从源服务器到 CDN 节点到 ISP(Internet Service Provider),全链路 HTTPS 通信

除此之外,CDN作为一种基础的云服务,同样具有资源托管、按需扩展(能够应对流量高峰)等方面的优势。

参考资料:

懒加载

懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。

在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能。

懒加载的好处

  • 减少无用资源的加载:使用懒加载明显减少了服务器的压力和流量,同时也减小了浏览器的负担。
  • 提升用户体验: 如果同时加载较多图片,可能需要等待的时间较长,这样影响了用户体验,而使用懒加载就能大大的提高用户体验。
  • 防止加载过多图片而影响其他资源文件的加载 :会影响网站应用的正常使用

懒加载与预加载的区别

这两种方式都是提高网页性能的方式。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。

  • 懒加载也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载,这样可以提高网站的首屏加载速度,提升用户的体验,并且可以减少服务器的压力。它适用于图片很多,页面很长的电商网站的场景。
  • 预加载指的是将所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。通过预加载能够减少用户的等待时间,提高用户的体验。预加载的最常用的方式是使用 js 中的 image 对象,通过为 image 对象来设置 scr 属性,来实现图片的预加载。

懒加载的实现原理

图片的加载是由src引起的,当对src赋值时,浏览器就会请求图片资源。根据这个原理,我们使用HTML5 的data-xxx属性来储存图片的路径,在需要加载图片的时候,将data-xxx中图片的路径赋值给src,这样就实现了图片的按需加载,即懒加载。

懒加载的实现重点在于确定用户需要加载哪张图片,在浏览器中,可视区域内的资源就是用户需要的资源。所以当图片出现在可视区域时,获取图片的真实地址并赋值给图片即可。

节流与防抖

概念

浏览器的 resizescrollkeypressmousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能

为了优化体验,限制调用次数,可以采用 防抖(debounce)节流(throttle) 的方式来减少调用频率

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

适⽤场景:

  • 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
  • 缩放场景:监控浏览器resize
  • 动画场景:避免短时间内多次触发动画引起性能问题

防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

适⽤场景:

  • 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
  • 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次

代码实现

节流

function throttle(fn, delay=500){
    let preTime = Date.now();
    return function(){
        let newTime = Date.now();
        if (newTime - preTime >= delay){
            fn.apply(null,arguments)
            preTime = Date.now();
        }
    }
}

function throttle2(fn,delay=500){
    let timer = null;
    return function(){
        if(!timer){
            timer = setTimeout(() => {
                fn.apply(this,arguments)
                timer = null
            },delay);
        }
    }
}

防抖

function debounce(fun, delay){
    let timer
    return function(){
        if (timer) clearTimeout(timer)
        let args = arguments
        timer = setTimeout(() =>{
            fun.apply(this,args)
        },delay)
    }
}

图片优化

小图用base64格式;

选择正确的图片格式:

  • 对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP 格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好

  • 小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替

  • 照片使用 JPEG

常见的图片格式及使用场景

  1. BMP,是无损的、既支持索引色也支持直接色的点阵图。这种图片格式几乎没有对数据进行压缩,所以BMP格式的图片通常是较大的文件。

  2. GIF是无损的、采用索引色的点阵图。采用LZW压缩算法进行编码。文件小,支持动画以及透明的优点。但是GIF格式仅支持8bit的索引色,所以GIF格式适用于对色彩要求不高同时需要文件体积较小的场景。

  3. JPEG是有损的、采用直接色的点阵图。优点是采用了直接色,更丰富的色彩适合用来存储照片,不适合用来存储企业Logo、线框类的图。因为有损压缩会导致图片模糊,而直接色的选用,又会导致图片文件较GIF更大。

  4. PNG-8是无损的、使用索引色的点阵图。PNG是一种比较新的图片格式,PNG-8是非常好的GIF格式替代者,在可能的情况下,应该尽可能的使用PNG-8而不是GIF,因为在相同的图片效果下,PNG-8具有更小的文件体积。除此之外,PNG-8还支持透明度的调节,而GIF并不支持。除非需要动画的支持,否则没有理由使用GIF而不是PNG-8。

  5. PNG-24是无损的、使用直接色的点阵图。PNG-24的优点在于它压缩了图片的数据,使得同样效果的图片,PNG-24格式的文件大小要比BMP小得多。当然,PNG24的图片还是要比JPEG、GIF、PNG-8大得多。

  6. SVG是无损的矢量图。SVG是矢量图意味着SVG图片由直线和曲线以及绘制它们的方法组成。SVG图片在放大时,不会失真,非常适合用来绘制Logo、Icon等

  7. WebP支持有损和无损压缩的、使用直接色的点阵图。从名字就可以看出来它是为Web而生的。相同质量的图片,WebP具有更小的文件体积。目前只有Chrome浏览器和Opera浏览器支持WebP格式,兼容性不太好。

    • 在无损压缩的情况下,相同质量的WebP图片,文件大小要比PNG小26%;
    • 在有损压缩的情况下,具有相同图片精度的WebP图片,文件大小要比JPEG小25%~34%;
    • WebP图片格式支持图片透明度,一个无损压缩的WebP图片,如果要支持透明度只需要22%的格外文件大小。