性能是前端开发一个非常重要的组成部分,与应用不同,网页的所有资源初始都需要通过网络传输,因此如何进行更好地进行网络传输对前端性能影响很大,此外还有浏览器渲染部分的优化。不管怎么说如何进行前端性能优化是一个永恒的话题。本文是阅读小册前端性能优化原理与实践后加上部分自己以前的理解整理而成的,更详细的原理请看小册。
概览文件:前端性能优化.xmind.zip
概述
性能优化需要从哪几个方面入手?我们要先了解浏览器打开网页的过程。
- 浏览器对URL进行DNS解析
- 浏览器与服务器进行TCP连接
- 浏览器发出HTTP请求
- 服务器返回HTTP响应
- 浏览器进行页面渲染
下面我们分别对这几个阶段进行优化。
浏览器进行DNS解析
DNS全称Domain Name System。它是互联网的“通讯录”,它记录域名与实际ip地址的关系,域名是为了方面人类记忆。每次我们方位一个网站,都要通过各级的DNS服务器查询到该网站的服务器ip,然后才能访问到该服务器。
提前解析DNS
提前解析DNS需要用到DNS prefetch
技术。可以在html中使用
<link ref="dns-prefetch" href="">
形式的标签来对特定域名进行预解析,浏览器会在页面加载完毕后进行该过程
另外还可以使用X-DNS-Prefetch-Control: on/off
响应头来控制预解析的开关。可以在html中使用
<meta http-equiv="x-dns-prefetch-control" content="on/off">
来实现该效果或直接让服务器返回该响应头。
与服务器建立TCP连接
TCP全称Transmission Control Protocol。是一种面向连接的,可靠的传输协议,它位于OSI模型的传输层。
浏览器发送HTTP请求
减少请求次数
-
资源合并
-
使用打包工具
使用webpack等工具,对js和css资源进行打包,避免js或css文件过多。
但也要考虑打包文件过大的问题,需要再这之间进行综合考虑。
在SPA中常用的实践是,webpack提取出的公用文件先加载,然后路由相关的文件按需加载。
-
精灵图
多个小图合并后的图片。
使用的时候使用background-position进行定位使用。
-
-
缓存
-
HTTP Cache(详细解释)
-
强缓存
强缓存的特定是不需要询问服务器,它通过expires和cache-control来实现。cache-control的优先级高于expires,它们都用来表示过期时间,expires是存储时间戳,cache-control使用max-age来表示相对时间。
cache-control 的no-cache不询问浏览器,直接请求服务器(进行协商缓存)。 而no-store则不是不使用任何缓存策略。 s-maxage只在代理服务器中生效。
如果资源没有过期,则会直接使用该资源。
-
协商缓存
协商缓存是请求服务器后,服务器来判断是返回新的资源,还是告诉浏览器使用旧的资源。
服务器每次返回资源会带有Last-Modified时间戳,每次服务器请求带上If-Modified-Since的时间戳,由服务器来判断资源修改时间是否与该时间一致。
last-modified有个问题是,虽然服务器文件修改时间变了,但是文件内容并没有真正变化
所有加入了ETag,是由文件内容计算出来的唯一标识。请求的时候会以If-None-Match带上该值,来由服务器判断
-
-
Service Worker Cache
-
Memory Cache & Disk Cache
他们是配合http缓存的。 memory cache命中最快,但是它周期较短,base64的图片,较小的js和css能够有较大几率被写进内存,这没有确定的定论。 其他较大的js、css和图片等会被直接写进硬盘,进行缓存。
-
-
存储(详细解释)
-
cookie
cookie最大为4k,通常用来存储一些用户登录状态,每次请求,浏览器都会带上相同域名下的cookie
-
webStrorage
webStorage分为两种,sessionStorage和localStorage,它们的大小在5-10M之间。都是以键值对的方式进行存储的。sessionStorage与localStorage的不同在于生命周期的不同,sessionStorage在tab关闭后,就不再存在了,而localStorage的永久存储,除非主动删除
-
indexDB
浏览器端的“数据库”,由于目前基本没用,所有暂不研究
-
缩小请求体积
-
资源压缩
-
Gzip
传输的时候可以在服务器端开启gzip压缩,可以有效减少传输文件的大小,可以在响应头content-encoding: gzip中看到。
-
代码压缩
使用一些代码压缩工具,删除掉无用的注释、空行和缩减名称等操作来减少文件体积。
-
图片压缩
图片是网页上占用很多流量的一种资源。如果在图片损失一些颜色和像素的情况下并不会对用户体验有太大影响,那么就应该对图片进行压缩。
同时可以对图片做一些裁切和缩小等操作,来减小图片的体积。
-
-
图片选用正确的格式(详细解释)
-
PNG
无损格式,压缩率一般,支持透明背景,常用于透明图片或者Icon等。
-
JPG
有损格式,压缩率较好,常用于复杂的大图,不支持透明背景。
-
SVG
矢量图形,可编程。在各分辨率下不失真,但是渲染复杂图形较消耗性能。常用于简单图形。
-
WEBP
无损格式,相较于PNG和JPG来说,压缩率更好,同时支持透明背景。唯一的缺点是兼容性不好。可用于兼容性好的浏览器,用JPG和PNG做回退机制。
-
服务器发送HTTP响应
减少响应时间
-
利用CDN
cdn全称content delivery network。它是依靠部署在各地区的边缘服务器,达到用户就近获取内容,降低网络拥塞,提高用户访问速度和命中率的目的。它主要的关键技术是内容存储和分发技术。
降低页面初始渲染时间
-
服务器渲染
服务器渲染最大的作用是优化SEO。
同时在性能上也能加快首屏渲染速度,但是这样会对服务器带来一定的压力,所以需要进行综合考量。
页面渲染(详细解释)
减少阻塞
-
JS阻塞
当html解析遇到js会先下载和执行js文件,这是为了防止js操作了dom等情况的发生。但我们作为操作者,可以人为的指定,那些元素可以延迟加载。
为script标签指定 async 或 defer来延迟脚本。
async表示js不会阻塞,但会在下载完成后立刻执行
defer则会在下载完成并且整个文档解析完成、DOMContentLoaded事件被触发前开始执行
-
CSS阻塞
css会阻塞html进行渲染,但是为了界面没有任何样式的展现在用户面前,因此我们需要将css提前
减少渲染次数
-
避免回流与重绘
回流又称为重排,即通过某种手段改变了元素的位置大小等信息,导致浏览器需要重新计算和渲染的过程。而重绘只是被改变了样式如背景和颜色等。
不论是哪一种,都会耗费性能,所以我们要避免进行循环操作。
减少渲染节点数量
-
懒加载
对于一些不在用户视图内的元素,我们可以在展示的时候先不进行渲染,直到该元素出现在了视图内再进行渲染。
懒加载包括对图片或者dom元素的加载和渲染
提高渲染效率
-
减少dom节点的操作
浏览器的渲染引擎和js引擎是分离的,可以想象在js引擎和渲染引擎之间进行”跨界交流“并不简单,这个开销很大,所有我们要尽量避免这种操作。
-
利用事件循环和异步更新(详细解释)