前端可优化的地方特别特别特别特别多,现在就从CRP方面简单说说。
输入URL到呈现页面过程:
CRP(Critical Rendering Path):关键路径渲染
关键流程一:浏览器渲染流程
1.构建DOM树、CSSOM树、渲染树
DOM树
转换,令牌,词法分析,DOM构建
2.CSSOM树
总结步骤:
1.处理 HTML 标记,构建 DOM 树
2.处理 CSS 标记,构建 CSSOM树
3.将DOM 树和 CSSOM 树融合成渲染树
4.根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流=》布局(Lavout)或重排(reflow)
5.根据渲染树以及回流得到的几何信息,得到节点的绝对像素=》 绘制( painting)或棚格化 (rasterizing )
注意:
真正渲染到页面的时候,一定发生在DOM树和CSSOM树都完成后,
HTTP和CSS都是阻碍页面渲染的东西。
优化方案
1.标签语义化
2.避免深层次嵌套(CSS选择器渲染是从右到左)
3.尽早尽快地把CSS下载到客端(充分利用HTTP多请求井发机制)
放到顶部:
style(html拿回来时候已经请求,比link更好一些)
link(发送HTTP请求,异步)
@import(减少import阻塞渲染的请求,同步)
4.避免阻塞的JS加载
放到底部
绿色:页面正在渲染
蓝色:遇到script请求拉取数据
红色:进行渲染
async声明的JS不要设置依赖
5.减少DOM的回流和重绘
页面渲染一次一定有回流和重绘,回流:元素大小或者位置发生变化。
重绘:样式的改变,例如背景颜色。
回流触发重绘,重绘不一定回流
避免回流:
1.放弃传统操作dom的时代,基于vue/react开始数据影响视图模式。
2.分离读写操作(现代浏览器都有渲染队列的机制)
3.样式集中改变
4.缓存布局信息
5.元素批量修改
6.动画效果应用到position属性为absolute或fixed的元素上(脱离文档流)
7.CSS3硬件加速(GPU加速)
8.牺牲平滑度换取速度
9.避免table布局和使用css的javascript表达式
关键流程二:DNS解析
DNS解析先在本地解析再去其他地方解析
1.DNS方面的优化(每一次DNS解析时间预计在20~120毫秒)
减少DNS请求次数(很难做到,现在网站一个网站从多个服务器返回资源)
DNS预获取(DNS Prefetch)
<link rel="dns-prefetch" href="https://d.jd.com"/>
复制代码
2.减少HTTP请求次数和请求资源大小
资源合并压缩、字体图标(不用矢量图,不独立发请求)、Base64、GZIP(一般文件压缩60%多)、图片懒加载、数据延迟分批加载、CDN资源(地域式分布)
3.应用缓存(第一次加载过后,重新加载,截止读取缓存)
缓存位置
常用的有:Memory Cache:内存缓存,Disk Cache:硬盘缓存
- 打开网页,地址栏输入地址:查找 disk cache 中是否有匹配,如有则使用,如没有则发送网络请求。
- 首通刷新(F5):因为 TAB 并没有关闭,因此memory cache 是可用的,会被优先使用(如果匹配的话),其次才是 disk cache.
- 强制刷新(Ctrl + F5):浏览品不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。
强缓存和协商缓存:
强缓存
强缓存离不开两个响应头 Expires,Cache-Control
Expires:Expires是http1.0提出的⼀个表示资源过期时间的header,它描述的是⼀个绝对时间,由服务器返回,
Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效
Expires: Wed, 11 May 2018 07:20:00 GMT
复制代码
Cache-Control: Cache-Control 出现于 HTTP / 1.1,优先级⾼于 Expires ,表示的是相对时间
Cache-Control: max-age=315360000
复制代码
⽬前主流的做法使⽤ Cache-Control 控制缓存, max-age 控制过期时间,还有以下指令
Cache-Control: public可以被所有⽤户缓存,包括终端和CDN等中间代理服务器
Cache-Control: private只能被终端浏览器缓存,不允许中继缓存服务器进⾏缓存
Cache-Control: no-cache,先缓存本地,但是在命中缓存之后必须与服务器验证缓存的新鲜度才能使⽤
Cache-Control: no-store,不会产⽣任何缓存
协商缓存
当第⼀次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过期抑或它的属性设
置为no-cache时,那么浏览器第⼆次请求时就会与服务器进⾏协商。
如果缓存和服务端资源的最新版本是⼀致的,那么就⽆需再次下载该资源,服务端直接返回304 Not Modified 状态码,
如果服务器发现浏览器中的缓存已经是旧版本了,那么服务器就会把最新资源的完整内容返回给浏览器,状态码就是200 Ok。
协商缓存生效,返回304
Last-Modi fied和If-Modified-Since
- 第一次访问资源,服务器返回资源的同时,响应头中设置 Last-Modified(服务器上的最后修改时间),浏览器接收后,緩存文件和响应头;
- 下一次请求这个资源,浏览器检测到有 Last-Modified,于是添加1f-Modified-Since请求头,值就是Last-Modified中的值:
- 服务品再次收到这个资源清求,会根据 if-Modifed-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果
- Modifed-Since的时间小于服务品中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200;
- 但是Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正磅的姿源;
协议缓存失败,返回200
ETag和If-None-Match
- Etag是服务器响应请求时,返回兰前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成;
- 下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到请求头If-None-Match里,服务器只需要比较客户端传来的if-None-Match跟白己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
- 如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源( 当然也包括了新的ETag) 发给客户端:如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
- 整体缓存流程图:
强缓存协商缓存都是针对文件的,针对数据可以用LocalStorage本地储存
另外的关键节点还有还有代码运行,代码编译,安全优化等
好了这就是个人的性能优化小笔记o(╥﹏╥)o,引用了一些博客还有珠峰培训的内容和图片,然后写的可能不是很完善很好,只是给自己复习的一个小笔记