谈谈前端性能优化

前端性能优化

初始阶段 —— 加载优化

首屏加载慢的优化

问题分析:

  • 首页加载图片过多
  • 首页的请求量过多
  • 首页请求的 静态资源(HTML、css、js、图片 …)过大

结论:所有加载慢的问题 最终都可以归纳为两个问题:多 和 大。tips:还有网速不好的或电脑配置差

问:首页加载图片过多怎么处理?
答:减少图片 ,通过懒加载的方式减少首屏加载量

问:懒加载是什么原理?
答:懒加载原理就是监听滚动条事件,如果(滚动条距离浏览器顶部的高度 === 图片距离顶部的高度),那么就把 data-src 的值赋值到 src 上,(setAttribute设置值到src属性上)

<img data-src="lazy.jpg">

<!-- 滚动到特定位置时-->
<img data-src-"lazy.jpg" src="lazy.jpg">

问:假设小图片就是很多,比如有很多icon怎么办?
答:
对于纯色系的小图标(矢量,放大不模糊)可以使用 iconfont 解决,设置font-family 的css属性,字体文件形式
对于一些彩色的小图片可以使用雪碧图 ,把所有的小图片拼接到一张大图片上,并使用 background-position 的 css属性来修改图片坐标

首页的请求量过多怎么解决

问题分析:
1、通过浏览器的network可以确定首页加载的资源和请求量

  • request :请求数量
  • resources:请求资源总大小
  • DOMContentLoaded:浏览器已经加载了HTML,其他静态资源(js,css,图片等)并没有下载完毕(能看,不能用,比如点击按钮不能用)
  • Load :浏览器已经加载了所有的静态资源(能用)

2、通过converge 来查看代码的使用情况

  • 只针对js和css
  • 可以看出哪些代码虽然加载了但是没有执行
  • 没有执行的代码可以考虑一下是否可以懒加载
    在这里插入图片描述

问:首页的请求量过多怎么解决?

答:可以减少资源的请求量,通过nginx服务来做资源文件的合并combo (插件:nginx-http-concat);通过打包工具webpack 来做资源文件的物理打包

问:只有合并资源这个方式才能减少资源请求量吗?

答:可以从代码层面的优化,1、如果在项目中引入比较大型的第三方库,那就可以通过特定的babel插件来进行按需加载;2、在路由层面也可以使用React lazy 进行动态路由的加载,从而减少首页的js和css大小;

问:为什么react lazy 可以进行动态路由的加载?

答:接收一个函数,这个函数动态调用import(),它必须返回一个promise,该promise需要resolve一个 default export 的 react 组件;

首页请求的资源(js、css、图片…)过大怎么解决?

问题分析:
把资源变小就完事

解决如下部分

一、资源合并和压缩

1、合并:减少http请求数量
2、压缩:减少请求资源的大小

  • HTML压缩
  • css压缩
  • js的压缩和混乱
  • 文件合并
  • 开启gzip

1、html压缩:
就是压缩这些在文本中有意义,但是在HTML中不显示的字符,包括空格,制表符,换行符等,还有一些其他意义的字符,如HTML注释也可被压缩。

如何进行html压缩?
(1)使用在线网站进行压缩(不过很少使用)
(2)nodejs提供了html-minifier工具
(3)后端模块进行引擎渲染压缩(服务端压缩)

2、css压缩:
无效代码删除(注释或无效字符)
css语义合并(语义重复)

如何进行css压缩?
(1)使用在线网站进行压缩
(2)使用html-minifier对html中的css进行压缩
(3)使用clean-css对css进行压缩

3、js压缩和混乱
(1)无效字符的删除(注释或回车,无效字符)
(2)剔除注释
(3)代码语义的缩减和优化(变量名缩短)
(4)代码保护(使代码混乱防止被别人窥探js源代码)

如何进行js压缩与混乱?
(1)使用在线网站进行压缩
(2)使用html-minifier对html中的js进行压缩
(3)使用ugifyjs2对js进行压缩

4、文件合并
在这里插入图片描述
但是不一定文件合并就是好的,文件合并也会存在的问题:
(1)首屏渲染问题(当使用框架时)
(2)缓存失效问题(如果js文件修改其中一个文件会导致合并后整体缓存失效)
建议:
(1)公共库合并(单独打包)
(2)不同页面的合并(单页应用,不同页面的js单独打包)
(3)见机行事,随机应变咯

5、如何进行文件合并?
(1)使用在线网站进行文件合并
(2)使用nodejs实现文件合并

在线JS/CSS/HTML压缩

在线JS/CSS/HTML压缩 https://tool.oschina.net/jscompress/

二、图片优化

1、png8/png24/png32的区别
png8——256色+支持透明
png24——2^24色+不支持透明
png32——2^24色+支持透明(24+8透明)
文件大小:色彩丰富程度,而每种图片格式都有自己的特点,针对不同业务业务场景选择不同的图片格式很重要!!!
2、图片常用的业务场景
(1)jpg有损压缩,压缩率较高,不支持透明(大部分不需要透明图片的业务场景)
(2)png支持透明,浏览器兼容好(大部分需要透明图片的业务场景)
(3)webp压缩程度更好,在iOS webview有兼容性问题(安卓全部)
(4)svg矢量图,代码内嵌,相对较小,图片格式相对简单的场景(图片样式相对简单的场景,比如logo,icon)
3、图片压缩
针对真实图片情况,舍弃一些相对无关紧要的色彩信息
(1)css雪碧图:减少网站的http请求数量(如果都集中一张图片会过大时,一次加载比较慢,导致页面渲染时都失去图片信息);
(2)image inline :将图片的内容都内嵌到html中,减少网站的http请求数量;
(3)使用矢量图:使用svg进行矢量图的绘制,iconfont解决icon问题
(4)在安卓下使用webp:它具有更优的图像数据压缩算法,能带来更小图片体积,而且拥有肉眼识别无差异的图片质量;同时具备了无损和有损的压缩模式、alpha透明以及动画的特性,在jpeg和png上的转化效果都非常优秀,稳定和统一。

图片压缩网址:熊猫站
雪碧图

https://tinypng.com/
http://www.spritecow.com/

三、css和js的装载和执行

1、html渲染过程的一些特点:
(1)顺序执行,并发加载(引入js外部资源)
(2)是否阻塞(css加载是否会阻塞js加载)
(3)依赖关系
(4)引入方式

  1. 顺序执行,并发加载
    (1)词法分析
    (2)并发加载
    (3)并发上限

  2. css阻塞
    (1)css head 中阻塞页面的渲染
    (2)css阻塞js的执行
    (3)css不阻塞外部加载的加载

  3. js阻塞
    (1)直接引入的js阻塞页面的渲染
    (2)js不阻塞资源的加载
    (3)js顺序执行,阻塞后续js逻辑的执行

四、懒加载和预加载

1、懒加载:
(1)图片进入可视区域之后请求图片的资源
(2)对于电商等图片很多,页面很长的业务场景适用
(3)减少无效资源的加载
(4)并发加载的资源过多会阻塞js的加载,影响网站的正常使用

2、预加载:
(1)图片等静态资源再使用之前提前请求
(2)资源使用到时能从缓存中加载,提升用户体验
(3)页面展示的依赖关系维护

比如九宫格抽奖机制、一些动画场景

五、重绘和回流

问题:css性能让js变慢吗?
频繁触发重绘和回流,会导致UI频繁渲染,最终导致js变慢;

回流
render tree 中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建,这就称为回流(reflow),当页面布局和几何属性改变时就需要回流。
重绘
render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局,比如background-color,则就称为重绘。
所以回流必将引起重绘,而重绘不一定会引起回流

1、触发页面重布局的属性
(1)盒子模型相关属性会触发重布局
(2)定位属性及浮动也会触发重布局
(3)改变节点内部文字结构也会触发重布局
如:width、height、padding、margin、dispaly、border、min-height;
top、bottom、left、right、position、float、clear;
text-align、over-flow-y、font-weight、font-size、font-family、line-height、vertival-align、white-space;

2、只触发重绘的属性
color、border-style、border-radius、visibility、text-decoration、background-image/position/repeate/size、outline-color/width、outline、box-shadow;
将频繁重绘回流的DOM元素单独作为一个独立图层,那么这个DOM元素的重绘和回流的影响只会在这个图层中。

如何将DOM元素变成新的独立图层?
例:Chrome创建图层的条件
1、3D或透视变换css属性(prespective transform)
2、使用加速视频解码的< video >节点
3、拥有3D(webGL)上下文或加速的2D上下文的< canvas >节点
4、混合插件(如Flash)
5、对自己的opacity做css动画或使用一个动画webkit变换的元素
6、拥有加速css过滤器的元素
7、元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)
8、元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上渲染)
比如:gif

当然避免的方法:

  • 避免使用触发重绘、回流的css属性
  • 将重绘和回流的影响范围限制在单独的图层之内

Chrome的performance
在这里插入图片描述

六、浏览器缓存

多种浏览器储存方式并存,如何选择呢?
在这里插入图片描述
cookie是什么
HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

打个比方,假如我去银行办理储蓄业务,第一次给我办了张银行卡,里面存放了身份证、密码、手机等个人信息,当下次再来这个银行时,银行机器能识别这张卡,从而能够直接办理业务。

七、节流和去抖

推荐:看之前的博客前端优化之节流和去抖

八、CDN加速

什么叫做cdn (内容分发网络)?
放静态资源的服务器(js、css、图片、字体…)

为什么用cdn可以实现加速?
cdn是解决方案,用nginx来实现的;

http1.1请求:对于同一协议、域名、端口、浏览器允许同时打开最多6个TCP连接(最多同时6个请求)
http2.0:引入多路复用的机制,可以最大优发送请求数量

答:
CDN服务器主要用来放静态资源的服务器,可以用来加速静态资源的下载
CDN之所以能过加速,是因为会在很多地方都部署CDN服务器,如果用户需要下载静态资源,会自动选择最近的节点下载
同时由于CDN服务器的地址一般都跟主服务器的地址不同,所以可以破除浏览器对同一域名发送请求的限制

运行阶段 —— 渲染优化

渲染十万条数据不造成卡顿

问题分析:
1、为什么渲染很多数据会造成浏览器卡顿?
2、怎么优化列表的情况

结论如下:
1、无论是浏览器中的DOM和BOM,还是nodejs,它们都是基于javascript引擎之上开发的
2、DOM和BOM的处理最终都要被转换为javascript引擎能够处理的数据
3、这个转换的过程是很耗时的
4、所以在浏览器中最耗时的就是操作DOM

怎么优化渲染很多数据的情况?
尽可能的减少dom的操作

结论:

1、可以使用document.createFragment 创建虚拟节点,从而避免引起没有必要的渲染
2、当所有的li 都创建完毕后,一次性把虚拟节点的li标签全部渲染出来
3、采用分段渲染的方式,比如一次只渲染一屏的数据
4、最后使用 window.requestAnimationFrame 来逐帧渲染

  // 优化方案之前
    console.time()
    let total = 10000
    let ul = document.querySelector('ul')
    function add() {
      // 1、创建虚拟节点,使用createDocumentFragment,不会触发渲染
      const fragment = document.createDocumentFragment()
      // 2、循环十万次
      for (let i = 0; i < total; i++) {
        const li = document.createElement('li')
        li.innerText = Math.floor(Math.random() * total)
        fragment.appendChild(li)
      }
      // 3、最后把虚拟节点 append 到ul 上
      ul.appendChild(fragment)
    }
    add()
    console.timeEnd();


    // 优化方案之后
    console.time()
    let total = 10000
    let ul = document.querySelector('ul')
    // 懒加载的思路,分段渲染
    // 1、一次渲染一屏的数量
    const once = 20;
    // 2、全部渲染完需要多少次,循环的时候要用
    const loopCount = total / once
    // 3、已经渲染多少次
    let countHasRender = 0
    function add() {
      // 1、创建虚拟节点,使用createDocumentFragment,不会触发渲染
      const fragment = document.createDocumentFragment()
      // 2、循环20次
      for (let i = 0; i < once; i++) {
        const li = document.createElement('li')
        li.innerText = Math.floor(Math.random() * total)
        fragment.appendChild(li)
      }
      // 3、最后把虚拟节点 append 到ul 上
      ul.appendChild(fragment)
      // 4、已渲染的次数 + 1
      countHasRender += 1
      loop()
    }
    // 最重要的是下面的部分
    function loop() {
      // 5、如果还没渲染完,那么用requestAnimationFrage 来渲染
      if (countHasRender < loopCount) {
        // requestAnimationFrame 叫做逐帧渲染
        // 类似于setTimeout(add, 16)
        // 帧:一秒播放多少张图片,一秒钟播放的图片最多,动画就越流畅
        // 1000/60 = 16
        window.requestAnimationFrame(add)
      }
    }
    loop()
    add()
    console.timeEnd();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值