前端| 性能优化总结

JavaScript/前端
354
0
0
2022-12-10

01

减少http请求,使用 HTTP2 :

HTTP1.1 如果要同时发起多个请求,就得建立多个 TCP 连接,因为一个 TCP 连接同时只能处理一个 HTTP1.1 的请求。在 HTTP2 上,多个请求可以共用一个 TCP 连接,这称为多路复用。同一个请求和响应用一个流来表示,并有唯一的流 ID 来标识。多个请求和响应在 TCP 连接中可以乱序发送,到达目的地后再通过流 ID 重新组建。

02

使用服务端渲染:

vuex中使用服务端渲染,服务器返回HTML文件,客户端只需解析HTML,利于SEO,首屏渲染快。

03

静态资源使用CDN,在多个位置部署服务器,让用户离服务器更近,从而缩短请求时间。

04

.css放在头部文件,js文件放在底部,css执行会阻塞渲染,阻止js执行

js加载和执行会阻塞HTML解析,阻止cssom构建

(cssom 指css object model,它和DOM类似,但是只针对CSS而不是HTML,浏览器将DOM和CSSOM结合来渲染web页面)

05

(1)使用字体图标iconfont代替图片图标

(2)压缩字体文件 fontmin0webpack对字体文件进行压缩

(3)压缩文件,使用webpack的插件比如js uglifyPlugin。css miniCssExtraPlugin,html htmlWebpackPlugin

(4)使用css3效果代替图片,如阴影、渐变等等

(5)使用webpack按需加载代码,提前第三方库,减少es6,es5代码冗余。如比如下拉选择国籍配置参数时,配置带上国旗和未带上国旗时大小差异很大、

06

.减少重绘重排,减少操作dom,dom元素的添加或删除,元素位置的改变,浏览器窗口尺寸改变。用 JavaScript 修改样式时,最好不要直接写样式,而是替换 class 来改变样式。下面有详情解释 。

  • 如果要对 DOM 元素执行一系列操作,可以将 DOM 元素脱离文档流,修改完成后,再将它带回文档。
  • 推荐使用隐藏元素(display:none)或文档碎片(DocumentFragement),都能很好的实现这个方案。

07

(1)使用事件委托,事件委托利用了事件冒泡。只指定一个事件处理程序,管理一类型的所有事件,节约内存。

(2)条件越多时,使用查找表代替switch和if-else。

const results = [result0,result1,result2,result3,result4,result5,result6,result7,result8,result9,result10,result11] return results[index]

const map = { red: result0, green: result1, } return map[color]

08

降低css选择器的复杂性:

浏览器读取选择器,遵循的原则是从选择器的右边到左边读取。

  1. 查找所有 P 元素。
  2. 查找结果 1 中的元素是否有类名为 text 的父元素
  3. 查找结果 2 中的元素是否有 id 为 block 的父元素

css 选择器优先级 内联>id>类>标签

  1. 选择器越短越好。
  2. 尽量使用高优先级的选择器,例如 ID 和类选择器。
  3. 避免使用通配符 *。

09

浏览器重绘(Repaint)和回流(Reflow):

回流必将引起重绘,重绘不一定会引起回流。

重绘(Repaint)

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

回流(Reflow)

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

(1) 页面首次渲染

(2) 浏览器窗口大小发生改变

(3) 元素尺寸或位置发生改变元素内容变化(文字数量或图片大小等等)

(4)元素字体大小变化

(5)添加或者删除可见的 DOM 元素

(6)激活 CSS 伪类(例如:hover)

(7) 查询某些属性或调用某些方法

(8) 一些常用且会导致回流的属性和方法

clientWidth/clientHeight/clientTop/clientLeftoffsetWidth/offsetHeight/offsetTop/offsetLeftscrollWidth/scrollHeight/scrollTop/scrollLeftscrollIntoView()/scrollIntoViewIfNeeded()/getComputedStyle()/getBoundingClientRect()/scrollTo()

性能影响:

回流比重绘的代价要更高。有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化:浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。

当你访问以下属性或方法时,浏览器会立刻清空队列:

clientWidth/clientHeight/clientTop/clientLeft offsetWidth/offsetHeight/offsetTop/offsetLeft scrollWidth/scrollHeight/scrollTop/scrollLeft width/height/getComputedStyle()/getBoundingClientRect()

因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

避免方法如下:

CSS

  • 避免使用 table 布局。
  • 尽可能在 DOM 树的最末端改变 class。
  • 避免设置多层内联样式。
  • 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。
  • 避免使用 CSS 表达式(例如:calc())。

Javascript

  • 避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
// 优化前 
const el = document.getElementById('test'); el.style.borderLeft = '1px'; el.style.borderRight = '2px'; el.style.padding = '5px'; 
// 优化后,一次性修改样式,这样可以将三次重排减少到一次重排 
const el = document.getElementById('test'); el.style.cssText += '; border-left: 1px ;border-right: 2px; padding: 5px;'
  • 避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
  • 也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
  • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
  • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。