Web前端性能优化
资源合并与压缩
Html压缩
HTML代码压缩就是压缩这些在文本文件中有意义,但是在HTML中不显示的字符,包括空格、制表符、换行符等,还有一些其他意义的字符,如HTML注释也可以被压缩。
压缩方式:
-
使用在线网站进行压缩
-
nodejs提供的html-minifier工具
-
后端模板引擎渲染压缩
Css、JS压缩与混乱
css:无效代码的删除、css语义合并,JS:无效字符的删除、剔除注释、代码语义的缩减和优化、代码保护。
压缩方式:
-
使用在线网站压缩
-
使用html-minifier对html中的Css进行压缩、对Html中JS进行压缩
-
使用clean-css对css进行压缩
-
使用uglifyjs2进行JS压缩
文件合并压缩
假设a.js、b.js、c.js三个文件,不合并压缩将会导致多次请求,文件与文件之间将会导致多个请求,增加网络延迟,丢包问题严重,keep-alive经过代理服务器获取资源也存在连接断开的问题。
文件合并存在的问题(合并结果abc.js),当渲染依赖于js文件时,将必须等到js文件加载,当合并文件abc.js太大,将会导致首屏渲染问题(空白页),例如Vue、React框架等,如果未使用服务端渲染时,必须要等框架代码加载完成,才能进行加载渲染,也会导致缓存失效问题,Js文件都是具有缓存性的,当任意一个文件被修改,都会导致全局abc.js文件改动。
改善:公共库合并(公共库与业务代码分割)、不同页面合并(对于单页面应用的某个页面被路由到才去发起请求,加载对应的页面组件)。
压缩方式:
- 使用在线网站进行文件合并
- 使用nodejs实现文件合并
图片优化
图片压缩
使用在线压缩工具压缩图片,减小图片体积,针对不同浏览器采用不同类型图片。
图片雪碧图
多张图片合并(雪碧图),通过css截取选取图片位置,注意:可以设计多张雪碧图,针对不同加载采用设计,防止全局图片依赖加载过程太长。
CSS和JS加载过程
输入浏览器地址,从服务器获取Html、JS、CSS数据,在页面构造中,解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本(并行)。解析过程中遇到图片、样式表、js文件,启动下载。
构建DOM树:
-
Tokenizing:根据HTML规范将字符流解析为标记
-
Lexing:词法分析将标记转换为对象并定义属性和规则
-
DOM construction:根据HTML标记关系将对象组成DOM树
构建CSSOM树:
-
Tokenizing:字符流转换为标记流
-
Node:根据标记创建节点
-
CSSOM:节点创建CSSOM树
构建RenderTree渲染树:
- 从DOM树的根节点遍历所有可见节点,不可见节点包括:
script
,meta
这样本身不可见的标签、被css隐藏的节点,如display: none
- 对每一个可见节点,找到恰当的CSSOM规则并应用
- 发布可视节点的内容和计算样式
JS解析过程:
- 浏览器创建document对象解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loading。
- 解析到无async和defer的script脚本,将他们添加到文档中,执行行内或者行外的脚本,同步执行,在脚本下载和解析过程中解析器会暂停,以document.write()写入页面。
- 当遇到async的脚本,会开始下载脚本,下载中页面仍然继续解析,脚本下载完成后会立即执行。
- 文档解析完成后,document.readstate状态转变为interactive。
- 所有defer脚本,将会按照在文档中出现的次序依次顺序执行。
- 注意:异步脚本执行,其中禁止使用document.write(),会导致页面结构改变。
- 浏览器在Document对象上触发DOMContentLoaded事件。
- 文档完全解析完成,但是可能存在类似图片加载未完成,等待这些内容加载完成并且所有异步脚本完成载入和执行,docume.readstate变为complete,window触发load事件。
- 逐步的显示页面。
HTML渲染过程的特点:
-
顺寻执行、并发加载。(浏览器并发存在上限)
-
是否阻塞。(css加载是否会阻塞页面渲染和JS执行等)
-
依赖关系。(css在head中才会显示最终渲染好附带样式的页面、否则可能从在无样式页面,async脚本执行无序)
-
引入方式。(css使用link还是@import方式,link会阻塞页面加载,@import实在页面解析完成后执行,JS引入方式async、defer、module )
懒加载和预加载
懒加载:对未进入可是区域中的图片,将真实地址放置在data-url中,当进入视野,替换src属性。
- 图片进入可视区域后请求图片资源
- 对于电商等图片很多,页面很长的业务场景适用
- 减少无效资源的加载
- 并发加载的资源过多会阻塞JS的加载,影响网站的使用
预加载:对于接下来将显示的内容进行预加载(例如:轮播时将下次显示的图片也加载出)。
- 图片等静态资源在使用之前的提前请求
- 资源使用到时能从缓存中加载,提审用户体验
- 页面展示的依赖关系维护
重绘与重流
重绘:当RenderTree中一些元素需要更新属性时,但是这些属性仅仅是影响元素的外观、风格,而不会影响布局的,比如background-color,则称为重绘。
回流:当RenderTree中一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建。这就成为回流。每个页面初次加载即发生回流。在回流中,因为渲染树中受影响的部分失效,并且重新构造这部分渲染树,完成回流后,则需要将绘制受影响内容重新替换到页面,则称为重绘。
区别:
- 回流将导致重绘,重绘不一定导致回流。
- 当页面布局和几何属性改变触发回流。
触发回流的页面布局条件:
盒子模型相关属性、定位属性以及浮动、改变节点内容,具体属性:
CSS属性:width height padding margin display border-width border min-height top left right bottom position float clear line-height text-align overflow-y font-weight overflow font-family vertival-align white-space font-size。
触发重绘的条件:
CSS属性:color、border-style、border-radius、visibility、text-decoration、background、background-image、background-position、background-repeat、background-size、outline-color、outline、outline-style、outline-width、box-shadow。
避免重绘、回流方法:
避免使用触发重绘、回流的CSS属性或者将重绘、回流的影响范围限制在单独的图层内,原因如下:
新建DOM过程:
- DOM将会被分割为多个图层
- 对每个图层的节点样式进行计算(Recalculate style--样式重新计算)。
- 为每个节点生成图形和位置(Layout--回流和重布局)。
- 将每个节点绘制填充到图层位图中(Paint SetUp 和 Paint--重绘)。
- 图层做为纹理上传至GPU。
- 符合多个图层到页面上生成最终屏幕图像(Composite Layers -- 图层重组)。
-
因此,将频繁重绘回流的DOM元素单独做为一个独立图层,该DOM元素的重绘和回流的影响只会影响这个图层,但是当图层太多,将会导致图层合并Composite Layers时间太长。除此之外,Chrome也存在创建图层条件:3D或透视变换CSS(transform 、perspective)、视频编码(video)、3D上下文或者加速的2D上下文的节点(WebGL 和 Canvas)、混合插件(Flash)、对opacity元素做动画或者使用一个动画webkit变换的元素、拥有加速CSS过滤器的元素、元素拥有子元素(子元素有属于自己的图层)、元素拥有z-Index属性且包含符合层的兄弟元素(图层上下位关系)。
图层查看方式: