通过面试题看性能优化

不管是自己之前面试还是看网上的面试题,都会碰到一个经典的面试题:从输入URL到页面加载完成,发生了什么?

首先说一下自己对于这道题的理解和回答:

  1. 用户在浏览器中输入URL
  2. 浏览器通过DNS,把url解析为IP
  3. 和IP地址建立TCP连接,发送HTTP请求
  4. 服务器接收请求,进行相关操作后返回的HTPP相应
  5. 浏览器收到首屏html,开始渲染
  6. 解析html为dom
  7. 解析css为css-tree
  8. dom + css生成render-tree绘图
  9. 加载script的js文件
  10. 执行js

所谓性能优化,就是上面的步骤加在一起,时间尽可能的短,所以基本分为两大方向:少加载文件,少执行代码。

快加载

 从上面的图中可以看出,浏览器渲染分为三步:

  • HTML解析文件,生成DOM树;解析CSS文件生成CSSOM树,两者并行
  • 将DOM树和CSSOM树结合,生成Render树
  • 根据Render树渲染回执,将像素渲染到屏幕上

从这个渲染流程图中,可以很容易得出下面的结论:

  • dom解析和css解析并行,css加载不会阻塞dom的解析
  • Render树是依赖于DOM树和CSSOM树的,所有css加载会阻塞DOM渲染
  • 由于js会影响之前的DOM和CSS,因此浏览器会维持HTML中的css和js的顺序,也就是说样式表会在后面的js执行前先加载完毕,也就是说,css加载会阻塞后面的js的执行

因此,可以从下面几个方面优化页面加载渲染速度:

  • 使用CDN
  • 压缩CSS,合并CSS(减少HTTP请求)
  • 合理使用缓存(版本号)

DNS(domain name service)

DNS服务就是将taobao.com这种域名解析为140.205.220.96

DNS查找过程

  1. 查看本地DNS缓存
  2. 本地没有缓存,发起DNS请求,向本地配置的DNS服务器请求

优化

  1. DNS预解析(prefetch预获取):先在浏览器中声明一些DNS解析的内容,因为DNS获取内容并不一次就能拿到全部的,而是通过不断的递归查询才能获取。

TCP

tcp负责数据的完整性和有序性,包括三次握手、四次挥手、粘包、滑动窗口等机制

 

从TCP的工作机制来看,这一阶段的优化策略主要包括以下几块

  1. 建立长连接
  2. 减少文件体积:js打包压缩、图片压缩、gzip
  3. 减少文件请求次数:雪碧图、缓存控制、懒加载
  4. 减少用户和服务取得距离:cdn
  5. 本地存储

TCP VS UDP

UDP适用场景:性能高、允许丢包、包本身特别小而不需要拆分、重发机制很好写  典型的就是dns

图片优化

图片通常是最占用流量的,PC端加载的平均图片大小是600K,简直比js打包后的文件还要大,所以针对图片的优化,也是收益不错的。图片方面的优化主要包括三块

  1. 图片格式问题
  2. 懒加载
  3. cdn

图片格式

不同的场景,使用不同的文件类型

jpg:

  • 有损压缩
  • 体积小
  • 不支持透明
  • 用于背景图、轮播图

png:

  • 无损压缩质量高
  • 支持透明
  • 色彩线条更丰富
  • logo、商品icon

svg:

  • 体积小的矢量图

代码少执行

防抖和节流

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

防抖就是作用是在短时间内多次触发同一个函数,只执行最后一次,或者只在开始时执行。节流是在一段时间内只允许函数执行一次。

回流(重排)和重绘

Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

回流必将引起重绘,而重绘不一定会引起回流。但是不管是回流还是重绘,都会影响性能。浏览器会帮助我们优化这些操作,浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。除此之外,我们自己也需要尽量的减少回流和重绘。

vue

  • 异步组件
  • 按需记载
  • 结合初始性能和频繁切换性能来决定使用v-if还是v-show
  • 和渲染无关的数据,不要放在data上,data也不要嵌套过多层
  • 合理使用nextTick(修改数据的当下,视图不会立刻更新,而是等同一时间循环中的所有数据变化完成之后,再同一进行视图更新)

react

  •  值传递需要的props,不要随便使用<Component {...props} />
  • 必要的key
  • 无状态组件
  • pureComponent  shouldComponentUpdate
  • 少在render中绑定事件

猜你喜欢

转载自www.cnblogs.com/yuyujuan/p/10872110.html