前端性能优化
web前端与CS架构GUI软件开发与部署过程
- CS架构GUI软件开发与部署过程:开发完成后通过生成包,发布到对应的应用下载商城之中,再将包放在对应的操作系统之中,最后代码将运行在该操作系统中,用户就可以访问加载在本地的一些资源。如:在安卓系统下,开发完成后打包会生成一个.apk的包,将该包发布在应用商城上,然后用户拿到该包后,就可以在安卓系统下去运行。
- web前端的开发与部署:当开发者开发完成之后是将项目运行在远程的服务器之中,用户就可以通过域名来访问该网址,从而就能访问到该项目。
web前端中一个请求从发送到返回所经历的过程
- 浏览器层面上:当用户访问url时,对应的url会通过domain到dns服务器,dns服务器会解析出ip,最后ip地址就会通过浏览器访问到对应的网络层
- 网络层面:此时通过该ip就会访问到对应的局域网然后通过交换机,再到路由器再到到主干网络最后到服务端
- 服务端:Controller层接收到数据,在Model层做数据交互(会拿db和redis中的数据),最后通过view层到网络,然后通过网络层面最后到浏览器中进行render
从网络请求过程中所存在的一些潜在优化点
从上面的请求过程中,就可以得到下面的优化点:
- dns是否可以通过缓存减少dns查询时间
- 网络请求的过程中是否走的是最近的网络环境
- 相同的静态资源是否可以缓存
- 能否减少请求http的http请求的大小
- 减少http请求
- 服务端渲染
下面就是从上面的优化点而衍生出的一些优化方案
资源合并与压缩
通过这个名称我们就可以很容易的知道,其所涉及到的性能优化点为:
- 减少http请求数量
- 减少请求资源的大小
html压缩
- 含义:压缩在文本文件中有意义,在HTML中不显示的字符,包裹空格,制表符,换行符等,还要一些有其他意义的字符,如HTML注释都可以被压缩
- 压缩方式:
- 使用在线网站进行压缩(不常用)
- nodeJS提供的html-minifier工具
- 后端模板引擎渲染压缩
- html压缩概述:html压缩在压缩的量上可能不会很大,从而可能会觉得其优化不能带来很大直观上性能的改变,但是需要注意的是如果一个网站访问的量如果很多,那么这样的优化方式所存在就是必然的。可以概述为一句常用的话为量变而达到质变
css压缩
- css压缩中的压缩点:
- 无效代码删除
- css语义合并
- css压缩方式
- 在线网站进行压缩
- 使用html-minifier对html中的css进行压缩
- 使用clean-css对css进行压缩
js压缩与混乱
-
压缩点:
- 无效字符的删除
- 剔除注释
- 代码语义的优化和缩减
-
js压缩和混乱实现方式
- 使用在线网站进行压缩
- 使用html-minifier对html中的js进行压缩
- 使用uglifyjs2对js进行压缩
-
js压缩概述:js压缩除了在性能优化上的作用外,其在保护代码上也达到了一定的作用,因为代码的可读性很差从而在一定程度上增加了代码的安全性
文件合并
对于文件合并主要从合并请求与不合并请求两方面看:
- 采用keep-alive不合并请求的方式:
- 存在的问题:
- 文件与文件之间有插入上的请求,会增加N - 1个网络延迟
- 受丢包问题影响更加严重
- 经过的代理服务器可能随时会被断开
- 采用合并请求的方式
- 存在的问题:
- 首屏渲染:页面在渲染的过程中会等js文件加载完成之后渲染,渲染页面由于js文件过多而导致加载速度变慢
- 缓存失效问题:将多个js文件合并为一个时,如果其中一个js文件改变会导致该文件的改变,从而会导致之前缓存的内容失效
- 文件合并所使用的业务场景
- 公共库的合并
- 不同页面之间的合并
- 其他(看具体的业务场景)
- 文件合并方式:
- 在线网站进行合并
- 使用构建工具进行文件合并,如webpack等构建工具
图片优化
首先需要去介绍的就是常见的图片格式的含义与特点:
- jpg:采用有损压缩的方式,在压缩的过程中会损失调一些无关的颜色,使得整个图片看起来在压缩前后没有区别
- png8:采用256色(即2^8)其支持透明处理,存在的特点为颜色支持小但其所消耗的资源相对较少
- png24:采用2^8存储颜色值,支持的色彩丰富度较png8而言更多,但是其不支持透明色的处理
- png32:采用2^8存储颜色值,支持的色彩丰富度多也支持透明色的处理
因而对于图片的应用需要从文件大小以及色彩的丰富度两个方面来处理
各个图片格式的特点:
- jpg有损压缩,压缩率高但是不支持透明
- png支持透明且浏览器兼容性较好
- webp压缩程度好,但是在ios webview上有兼容性问题,即对ios的支持度不好
- svg矢量图,代码内嵌,相对较小图片样式相对较少
图片格式的使用场景:
- jpg——大部分不需要透明图片的业务场景
- png——大部分需要透明图片的业务场景
- webp——安卓全部
- svg——图片样式相对简单的业务场景
图片优化的几种方式
- 进行图片压缩:针对真实图片的情况,舍弃一些无关紧要的色彩信息(常用于压缩图片的网站为:https://tinypng.com/ ,其能够保证图片在不失帧的情况下将图片压缩到最小)
- css雪碧图:把网站上用到的一些图片整合到一张单独的图片中
- 优点:
- 减少网站的http请求数量
- 缺点:
- 当图片加载不出时,会出现页面上所有需要该图片的部分都显示不出,影响渲染效果
- 当修改图片时,重新拼接图片等,有的需要重新进行裁剪,在维护上不方面
- Image inline:将图片的内容内嵌到html中,减少网站的http请求数量。使用方式为:let 变量 = _inline(url), src = 变量
- 使用矢量图:使用svg进行矢量图的绘制,如使用iconfont解决icon问题
- 使用webp格式的图片:webp优势体现在其具有更优的图像数据压缩算法,能带来更小的图片体积;同时具备有损和无损的压缩模式、Alpha透明以及动画的特性,在jpeg和png上的转化效果非常优秀和稳定
图片的懒加载
- 含义:当图片进入到可视区域之后去请求图片的资源
- 使用场景:对于电商网站需要加载很多图片,页面很长时适用
- 作用:减少无效资源的加载,增强页面的性能,有更好的交互体验
- 影响:并发加载的资源过多时,会阻塞js的加载,影响网站的正常适用
- 懒加载的实现方案:
- 采用原生js实现
- 使用lazyload插件https://www.lazyloadjs.cn/
图片的预加载
- 含义:图片等资源在使用之前就预先加载,提前请求
- 作用:资源使用时能从缓存中加载,提升用户体验
- 预加载实现方式:
- 在img标签中使用display:none
- 在js中新建image对象,将图片资源放在该对象之中
- 使用XMLHttpRequest对象
- 使用preload插件https://github.com/imweb/preload
浏览器渲染过程中的一些优化点
首先需要了解的就是整个浏览器在渲染过程中是怎样一个过程,其渲染过程如下:
- 拿到html文档
- 解析html生成一个dom树,解析css生成一个css树
- 将dom树与css树结合渲染生成一个render树
- layout(回流):根据生成的render树,进行回流,得到节点的几何信息
- painting(重绘):根据render树以及回流得到几何信息,从而得到节点的绝对像素
- display:将像素发给gpu经过计算最终展示在页面
html在渲染过程中的一些特点
-
顺序执行、并发加载
- 并发加载:在加载过程中会引入css以及js资源在浏览器端并发加载,但是需要注意的是并发加载是受并发度所影响的,因为在一个域名下其加载资源的量是有一定限度的,其解决方式是将很多的资源都放在cdn上,通常情况下会设置三到四个域名,这样能防止一个域名下资源并发上限
- 是否阻塞:
- css加载是否会阻塞js加载
- js的加载是否会影响后续的js执行
- css加载是否会影响页面的渲染
- 依赖关系:html文件之间的依赖关系,如何保证在html中依赖关系正常的情况下来提升效率
- 引入方式
顺序执行、并发加载
- 词法分析:浏览器对html文档的一种解析方式,其加载的方式是按照顺序从上到下执行的,其会影响一些资源的引入过程
- 并发加载
- 并发上线
css阻塞
- css header阻塞页面的渲染:利用该特点可避免页面闪动,将css放在header之中会阻塞页面的渲染,需要等css加载完成之后才会去执行之后的内容,这样可避免页面的闪动
- css阻塞js的执行:造成该现象的原因是有的js操作会影响到css样式的更改等
- css不阻塞外部脚本的加载
js阻塞
- 直接引入的js会阻塞页面的渲染
- js不阻塞资源的加载:在浏览器的内核中如webkit有预加载器,当执行到需要加载资源的部分时,就会先加载资源
- js顺序执行:在js顺序执行时,也会影响到后续js的逻辑执行
css性能与js之间的关系
在这两者之间存在着一定的关系,即css性能会让js执行变慢,造成这个的原因是因为在频繁的出现回流与重绘时,会导致UI频繁渲染,最终导致js执行变慢
回流
- 含义:当render tree中的一部分(或全部),因为元素的规模尺寸、布局或者是隐藏等改变而导致需要重新计算Dom节点及其样式在设备视口内的确切位置和大小时,该阶段就被称之为回流
- 造成回流的因素:
- 盒子模型相关属性的改变
- 获取定位元素以及浮动
- 改变节点内部文字结构
重绘
- 含义: 当render tree中的一些元素需要重新更新属性并且这些属性只影响元素的外观以及风格,而不影响布局,即将回流阶段获得的具体集合信息(位置、大小)转换成屏幕上的实际像素,该阶段被称之为重绘节点即重绘
- 造成重绘的因素:
- color border-style border-radius visibility text-decoration background等只影响元素外观及风格的元素
基于重绘与回流优化
对于该部分首先需要理解新建dom过程:
- 获取Dom之后分割图层
- 对于每个图层的节点计算样式结果(Recalulate style-样式重计算)
- 为每个节点生成生成图形和位置(layout-回流和重布局)
- 将每个节点绘制填充到图层位图中(paint setup和paint-重绘)
- 图层作为纹理上传至gpu
- 符合多个图层到页面上生成最终屏幕图像(composite layers-图层重组)
从新建dom的过程可知,在页面的性能提升上可以获得的优化点为:- 避免使用触发重绘、回流的css属性
- 将重绘、回流的影响范围限制在单独的图层中
从这里的优化点可知,如果要将重绘、回流限制在单独的图层中需要知道的就是怎样去创建一个图层,在chrome中创建图层的条件如下:
- 3D或透视变化css属性(perspective transform)
- 使用加速视频解码的video节点
- 拥有3D(WebGL)上下文或加速的2D上下文的canvas节点
- 混合插件(如flash)
- 使用opacity做动画或使用一个动画的webkit变换元素
- 拥有加速css过滤器的元素
- 元素有一个包含复合层的后代界面(一个元素拥有一个子元素,该子元素在自己的层里)
- 元素有一个较低的z-index且包含一个复合层的兄弟元素(即该元素在复合层上的渲染)
基于重绘与回流的优化点:
- 用translate代替top的改变
- 用opacity代替visibility
- 不要一条一条的修改dom样式,预定定义好clas,然后再修改DOM的className
- 把DOM离线修改
- 不要使用table布局,可能一个很小的改动都会造成table的重新布局,应该尽量使用div
- 动画实现速度的选择
- 用动画新建图层
- 启用GPU硬件加速,使用transform来开启GPU硬件加速
缓存相关
对于从缓存方面来优化页面就需要知道以下两点:
- localStorage、cookie、sessionStorage以及indedb的概念及应用
- 理解pwa和service worker的应用
cookie
- 常用业务场景:去保存浏览器端或者客户端的信息,发送到服务器,去辨别用户
- 使用原因:因为http请求无状态,使用cookie去维持客户端的状态
- cookie的生成方式:
- http response header中set-cookie
- js中可通过document.cookie去读写cookie
- 作用:
- 用于浏览器端与客户端的交互
- 客户端自身数据的存储(仅仅是存储浏览器端的一些信息)
- cookie存储的限制:
- 作为浏览器存储,其大小4kB左右
- 需要设置过期时间expire
- httponly不支持浏览器端读写(从安全性上考虑,因而其属性值常常被设置为true)
- 缺点:cookie在相关域名下会有cdn的流量损耗
- 解决方式:cdn域名和主站的域名要分开
localStorage
其具有以下的几个特点:
- html5设计出专门用来做浏览器存储的
- 其大小为5M左右
- 仅在客户端使用,不和服务端做通信
- 接口封装较好,可以直接使用方法
- 常用于作为浏览器本地缓存方案(防止首屏渲染出现加载不出信息而出现白屏现象)
sessionStorage
其具有以下特点:
- 会话级别的浏览器存储方案,会话已结束自动清除存储内容
- 大小为5M左右
- 仅在客户端使用,不和服务端进行通信
- 接口封装较好
- 常用于表单信息的维护(表单进行多页面应用传递时使用)
浏览器中的分级缓存策略
该分级缓存的顺序依次为:
- 200状态(form cache):这一层由expires/cache-control控制
- expires(http1.0版本有效),是绝对时间
- cache-control(http1.1版本有效),相对时间
- 优先级:当两者都存在时,cache-control覆盖expires只要没失效,浏览器只访问自己的缓存
- 304状态:该层由last-modified/etag控制,当下一层失效时或者这用户重新刷新时,浏览器就会发送请求到服务端,如果服务端没有变化就返回304,此时浏览器就会使用缓存中的内容
- 200状态:当浏览器中没有缓存,或者是下一层失效时或者用户刷新,浏览器直接去服务端下载最新的资源
- etag与last-modified之间的异同点以及优先级
- 相同点:都需要与cache-control结合使用
- 不同点:
- etag:
- 文件的内容为hash值,
- etag——>response header,if-none-match——>request header
- last-modified
- 文件内容为时间
- last-modified ——>response header,if-modified-since——>request header
- 其存在的缺点:1. 某些服务端不能获取精确的修改时间;2. 存在文件时间修改了,文件内容没变的情况
indexDB
- 含义:是一种低级的API,用户客户端存储大量结构化数据,该API使用索引来实现对该数据的高效性能搜索,虽然Web Storage存储较少量的数据很有用,但是对于存储大量的结构化数据来说,这种方式就不太可取。因而indexDB就提供了这样的一种解决问题的方案
- 应用场景:为应用创建离线版本
PWA
- 含义:一种新型的web app模型,并不是具体指某一种前言的技术或者单一的知识点,其是一个渐进式的Web App,是通过一系列新的Web特性,配合优化的UI交互设计,逐步的增强Web App的用户体验
- 可靠:在没有网络的环境中也能提供基本的页面访问,而不是会出现"未连接到互联网"的页面
- 快速:针对网页渲染以及网络数据访问有较好的优化
- 融入:应用可以被添加到手机桌面,并且和普通应用一样有全屏、推送的特性
- lighthouse:(download: chorme application station),可以运行lighthouse去测试该web app对于pwa应用的性能检测
service worker
- 含义:是一个脚本,浏览器独立于当前页面,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开,在未来这些特性包括,推送消息,背景后台同步,geofencing(地理围栏定位),但它将推出一个首要特性就是拦截和处理网络请求的能力(包括以编程式的方式来管理被缓存的响应)
- 应用场景
- 使用拦截和处理网络请求的能力去实现一个离线应用
- 使用其在后台运行同时能和页面通信的能力,去实现大规模后台数据的处理
- service woker生命周期:
- No Service Worker到Installing
- 如果安装成功就进入激活状态,否则则报一个error
- 进入激活状态之后就直接进入IDLE(集成开发环境)
- 最后idle状态也可以进入到terminated或者是fetch/message,两者之间可以互换
- service worker的调试工具
- chrome://serviceworker-internals/
- chrome://inspect/#service-workers
服务端性能优化:
- 理解vue渲染遇到的问题:
- 在没有前端框架时:用jsp/php在服务器端进行数据的添充,发送给客户端就是已经添从好数据的html
- 在有前端框架时:进行异步加载数据,使用vue或者是前端框架
- 在有前端框架时,在客户端首屏渲染时,会有延迟,如以vue框架写的项目会进行如下过程
- 加载vue.js
- 进行vue相关逻辑的执行
- 加载html
- 多层次的优化方案:
- 构建层模板编译
- 数据无关的prerender的方式
- 服务器性能优化
- 学习理解vue-ssr的原理和应用
- vue-ssr原理图:
从这个图中可以看到在source部分,universal Application code部分就是我们我们使用vue所写的项目的代码部分,所有的这部分代码有一个公共的入口就是app.js这个文件,这个文件又被分成了两个部分,service entry(服务端入口)和client entry(客户端入口),最后被webpack构建到浏览器中,最后生成两个bundle,分别为Server Bundle和Client Bundle。最后在node server端将bundle renderer给渲染成html模板,再将浏览器中的client bundle中的内容混入到该html模板中,然后渲染出整个的页面。
- vue-ssr原理图:
- vue-ssr应用:
因而从中我们可以做一些事情,例如将一些内容放在服务器端去进行处理直接给渲染成html模板,这样利用服务端的计算能力来处理,从而来提升页面的性能