经常使用前端性能优化总结大全,体验飞通常的感受~

前言

性能优化,一直做为前端的一个热点问题,做为一个优秀的前端开发人员,性能优化时必备技能。本文将从减小http请求次数、减小单次请求资源大小、渲染优化、资源加载优化等四个大方向,下分诸多小方向,全面总结经常使用前端优化方法。 (内容较多请看目录)css

减小http请求次数

1.浏览器缓存策略

浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列以下:
html

  • Memory Cache:是指存在内存中的缓存。从优先级上来讲,它是浏览器最早尝试去命中的一种缓存。从效率上来讲,它是响应速度最快的一种缓存。浏览器秉承的是“节约原则”,咱们发现,Base64格式的图片,几乎永远能够被塞进memory cache,这能够视做浏览器为节省渲染开销的“自保行为”;此外,体积不大的JS、CSS文件,也有较大地被写入内存的概率——相比之下,较大的JS、CSS文件就没有这个待遇了,内存资源是有限的,它们每每被直接甩进磁盘。
  • Service Worker Cache:是一种独立于主线程以外的Javascript线程。它脱离于浏览器窗体,所以没法直接访问DOM。这样独立的个性使得 Service Worker的“我的行为”没法干扰页面的性能,这个“幕后工做者”能够帮咱们实现离线缓存、消息推送和网络代理等功能。咱们借助 Service worker 实现的离线缓存就称为Service Worker Cache。
  • HTTP Cache:它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的状况下,才会走协商缓存。
      强缓存是利用http头中的Expires和Cache-Control两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的 expires 和 cache-control判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通讯。
      协商缓存依赖于服务端与浏览器之间的通讯。协商缓存机制下,浏览器须要向服务器去询问缓存的相关信息,进而判断是从新发起请求、下载完整的响应,仍是从本地获取缓存的资源。若是服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种状况下网络请求对应的状态码是304。
  • Push Cache:是指 HTTP2 在 server push 阶段存在的缓存。Push Cache 是缓存的最后一道防线。浏览器只有在 Memory Cache、HTTP Cache 和 Service Worker Cache 均未命中的状况下才会去询问 Push Cache。
      Push Cache 是一种存在于会话阶段的缓存,当 session 终止时,缓存也随之释放。不一样的页面只要共享了同一个 HTTP2 链接,那么它们就能够共享同一个 Push Cache。

2.CDN

  CDN 的核心点有两个,一个是缓存,一个是回源。
  “缓存”就是说咱们把资源 copy一份到CDN服务器上这个过程,“回源”就是说CDN发现本身没有这个资源(通常是缓存的数据过时了),转头向根服务器(或者它的上层服务器)去要这个资源的过程。
  CDN每每被用来存放静态资源。所谓“静态资源”,就是像 JS、CSS、图片等不须要业务服务器进行计算即得的资源。用户能够从一个较优的服务器获取数据,从而达到快速访问,并减小源站负载压力的目的。
  另外,CDN的域名必须和主业务服务器的域名不同,要不,同一个域名下面的Cookie各处跑,浪费了性能流量的开销,CDN域名放在不一样的域名下,能够完美地避免了没必要要的 Cookie 的出现!前端

3.图片处理

  • sprite雪碧图:CSS雪碧图是之前很是流行的技术,把网站上的一些图片整合到一张单独的图片中,能够减小网站的HTTP请求数量,可是当整合图片比较大时,一次加载比较慢。随着字体图片、SVG图片的流行,该技术渐渐退出了历史舞台。
  • base64图片编码:将图片的内容以Base64格式内嵌到HTML中,能够减小HTTP请求数量。可是,因为Base64编码用8位字符表示信息中的6个位,因此编码后大小大约比原始值扩大了 33%
  • 字体图标:字体图标经过本身规定字体的unicode编码,找到文件后根据unicode码去查找绘制外形,以文字的形式代替图片。

4.文件合并

将公共的js、css样式合并为一个大文件。
根据不一样页面的需求单独合并所需js、css文件。web

5.减小重定向

  尽可能避免使用重定向,当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达以前,页面中不会呈现任何东西,也没有任何组件会被下载,下降了用户体验。
  若是必定要使用重定向,如http重定向到https,要使用301永久重定向,而不是302临时重定向。由于,若是使用302,则每一次访问http,都会被重定向到https的页面。而永久重定向,在第一次从http重定向到https以后,每次访问http,会直接返回https的页面。浏览器

减小单次请求资源大小

6.css压缩、图片压缩、gzip压缩、js混淆等

css压缩,就是进行简单的压缩,压缩空白等。
图片压缩,主要也是减少体积,在不影响观感的前提下,能够删除一些可有可无的色彩。另外可使用webp格式图片。
gzip压缩主要是针对html文件来讲的,它能够将html中重复的部分进行一个打包,屡次复用。
js混淆能够有简单的压缩(将空白字符删除)、丑化(将一些变量缩小)、或者对js进行混淆加密。缓存

渲染优化

7.优化css选择符

CSS 选择符是从右到左进行匹配的,好比 #myul li {}实际开销至关高。所以须要对选择符进行优化,主要有以下几方面:性能优化

  • 避免使用通配符*,只对须要用到的元素进行选择。
  • 少用标签选择器。若是能够,用类选择器替代。错误:#dataList li{} 正确:.dataList{}
  • 关注能够经过继承实现的属性,避免重复匹配重复定义。
  • 不要多此一举,id 和 class 选择器不该该被多余的标签选择器拖后腿。错误:.dataList#title 正确:#title
  • 减小嵌套。后代选择器的开销是最高的,所以咱们应该尽可能将选择器的深度降到最低(最高不要超过三层),尽量使用类来关联每个标签元素。

8.减小回流和重绘次数

  • 回流:当咱们对 DOM 的修改引起了 DOM 几何尺寸的变化(好比修改元素的宽、高或隐藏元素等)时,浏览器须要从新计算元素的几何属性(其余元素的几何属性和位置也会所以受到影响),而后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。
  • 重绘:当咱们对 DOM 的修改致使了样式的变化、却并未影响其几何属性(好比修改了颜色或背景色)时,浏览器不需从新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫作重绘。

重绘不必定致使回流,回流必定会致使重绘。bash

9.减小DOM操做

从上面能够知道,DOM改变容易引发回流和重绘,所以咱们要减小DOM操做。 例子剖析,以下代码:服务器

for(var count=0;count<10000;count++){ 
  document.getElementById('container').innerHTML+='<span>我是一个小测试</span>'  //咱们每一次循环都调用 DOM 接口从新获取了一次 container 元素,额外开销
} 
复制代码

进化一babel

// 只获取一次container
let container = document.getElementById('container')
for(let count=0;count<10000;count++){ 
  container.innerHTML += '<span>我是一个小测试</span>'
} 
复制代码

进化二
考虑JS 的运行速度,比 DOM 快得多这个特性。咱们减小 DOM 操做的核心思路,就是让 JS 去给 DOM 分压。

//减小没必要要的DOM更改
let container = document.getElementById('container')
let content = ''
for(let count=0;count<10000;count++){ 
  // 先对内容进行操做
  content += '<span>我是一个小测试</span>'
} 
// 内容处理好了,最后再触发DOM的更改
container.innerHTML = content
复制代码

进化三
在 DOM Fragment 中,DocumentFragment 接口表示一个没有父级文件的最小文档对象。它被当作一个轻量版的 Document 使用,用于存储已排好版的或还没有打理好格式的XML片断。由于 DocumentFragment 不是真实 DOM 树的一部分,它的变化不会引发 DOM 树的从新渲染的操做(reflow),且不会致使性能等问题。

let container = document.getElementById('container')
// 建立一个DOM Fragment对象做为容器
let content = document.createDocumentFragment()
for(let count=0;count<10000;count++){
  // span此时能够经过DOM API去建立
  let oSpan = document.createElement("span")
  oSpan.innerHTML = '我是一个小测试'
  // 像操做真实DOM同样操做DOM Fragment对象
  content.appendChild(oSpan)
}
// 内容处理好了,最后再触发真实DOM的更改
container.appendChild(content)
复制代码

进化四
当涉及到过万调数据进行渲染,并且要求不卡住画面,如何解决? 如何在不卡住页面的状况下渲染数据,也就是说不能一次性将几万条都渲染出来,而应该一次渲染部分 DOM,那么就能够经过 requestAnimationFrame 来每 16 ms 刷新一次。

setTimeout(() => {
        // 插入十万条数据
        const total = 100000
        // 一次插入 20 条,若是以为性能很差就减小
        const once = 20
        // 渲染数据总共须要几回
        const loopCount = total / once
        let countOfRender = 0
        let ul = document.querySelector('ul')
        function add() {
          // 优化性能,插入不会形成回流
          const fragment = document.createDocumentFragment()
          for (let i = 0; i < once; i++) {
            const li = document.createElement('li')
            li.innerText = Math.floor(Math.random() * total)
            fragment.appendChild(li)
          }
          ul.appendChild(fragment)
          countOfRender += 1
          loop()
        }
        function loop() {
          if (countOfRender < loopCount) {
            window.requestAnimationFrame(add)
          }
        }
        loop()
      }, 0)
复制代码

10.使用事件委托

  事件委托是指将事件监听器注册在父级元素上,因为子元素的事件会经过事件冒泡的方式向上传播到父节点,所以,能够由父节点的监听函数统一处理多个子元素的事件。利用事件委托,能够减小内存使用,提升性能及下降代码复杂度。

11.节流和防抖

  当用户进行滚动,触发scroll事件,用户的每一次滚动都将触发咱们的监听函数。函数执行是吃性能的,频繁地响应某个事件将形成大量没必要要的页面计算。所以,咱们须要针对那些有可能被频繁触发的事件做进一步地优化。节流与防抖就颇有必要了!

  • 函数节流: 频繁触发,但只在特定的时间内才执行一次代码
  • 函数防抖: 频繁触发,但只在特定的时间内没有触发执行条件才执行一次代码 //防抖函数
//节流函数
function throttle(fn,time){
	var last = 0;
	return function(){
		var context = this;
		var now = Date.now();
		if (now - last >= time){
			fn.apply(this, arguments);
			last = now;
		}
	};
}
//防抖函数
function debounce(fn, time){
	return function(){
		var context = this;
		clearTimeout(timeId);
		timeId = setTimeout(function(){
			fn.apply(context, arguements);
		}, time);
	};
}
复制代码

资源加载优化

12.资源预加载和懒加载

  • 懒加载会延迟加载资源或符合某些条件时才加载某些资源。
  • 预加载是提早加载用户所需的资源,加速页面的加载速度,保证良好的用户体验。

资源懒加载和资源预加载都是一种错峰操做,在浏览器忙碌的时候不作操做,浏览器空间时,再加载资源,优化了网络性能。

13.css、js文件引用位置优化

  • CSS文件放在head中,先外链,后本页。
  • JS文件放在body底部,先外链,后本页。
  • body中间尽可能不写style标签和script标签。
  • 处理页面、处理页面布局的JS文件放在head中,如babel-polyfill.js文件、flexible.js文件。
相关文章
相关标签/搜索