web前端性能优化
一、资源合并与压缩
-
1.html压缩,可使用html-minifier
-
2.css压缩,可使用clean-css
-
无效代码删除
- 删除注释
- css语义合并
-
3.js压缩,可使用uglifyjs2
-
无效字符的删除
- 删除注释
- 剔除注释
- 代码予以的缩减和优化,更改变量名来简短变量名的长度
二、图片优化
-
1.不同场景选择不同格式的图片
-
jpeg:有损压缩,压缩率高,不支持透明
- png:支持透明
-
png8:2^8种颜色,支持透明,png中大小最小
* png24:2^24种颜色,不支持透明
* png32:2^24种颜色,加8位支持透明,png中大小最大- webp:压缩程度更好,支持无损压缩和有损压缩,google推出的,支持Android
- svg:矢量图,代码内嵌,相对较小,适用于icon
-
2.图片压缩
-
css雪碧图:利用background-position来获取相应的图片,解析雪碧图样式
-
优点:减少http请求数量
* 缺点:整合图片比较大时,一次加载比较慢- 图片image-inline:将图片内容转化为base64内嵌到html当中
-
优点:减少http请求数量
* 缺点:整体的文件大小会变大- icon使用矢量图
-
优点:减小大小,且放大不会失真
- 在安卓下用webp
-
优点:比jpeg和png更优的压缩算法,能带来更小的体积,支持无损压缩和有损压缩
-
3.在线压缩
-
TinyPNG
- 智图 图片优化平台
-
4.懒加载
-
原理:可视区域外img标签不设置src属性,通过scroll事件监听img标签进入可视区域后设置src属性
-
5.预加载
-
直接使用image标签,如<img src="图片链接" style="display:none;" />
-
使用Image对象
-
1
2
3
4 1var img = new Image();
2img.src = '图片链接'
3
4
1
2 1* 使用XMLHttpRequest对象
2
1
2
3
4
5
6
7 1var xhr = new XMLHttpRequest();
2xhr.onreadystatechange = 回调函数;
3xhr.onpregress = 进度回调函数;
4xhr.open('GET','图片链接',true);
5xhr.send();
6
7
-
优点:更加精细地控制整个预加载过程
* 缺点:会存在跨域问题-
使用preloadjs库
-
三、避免重绘和回流(css渲染会阻塞js执行)
重绘:元素更新属性,不影响元素布局,只影响元素的外观、风格,这就是重绘。
回流:当render tree中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就是回流(重排)。
ps:回流一定会重绘,重绘不一定会回流。
优化方式:
-
1.避免使用触发重绘、回流的CSS属性
-
会导致页面重布局的属性:
-
(1) 盒子模型相关属性
-
width
* height
* padding
* margin
* display
* border-width
* border
* min-height1
21 * (2)定位属性及浮动
2 -
top
* bottom
* left
* right
* position
* float
* clear1
21 * (3)改变节点内部文字结构
2 -
text-align
* overflow-y
* font-weight
* overflow
* font-family
* line-height
* vertical-align
* white-space
* font-size- 只会触发重绘的属性:
-
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 -
2.限制重绘回流的范围
将重绘、回流的影响范围限制在单独的图层之内。
将频繁重绘回流的DOM元素单独作为一个独立图层,那么这个DOM元素的重绘和回流的影响只会在这个图层中。
-
chrome中创建图层的方法:
-
3D或透视变换CSS属性(perspective transform)
* 使用加速视频解码的<video>节点
* 拥有3D(WebGL)上下文或加速的2D上下文的<canvas>节点
* 混合插件(如Flash)
* 对自己的opacity做CSS动画或使用一个动画webkit变换的元素
* 拥有加速CSS过滤器的元素
* 元素有一个包含符合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)
* 元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)- 创建图层的css例子
-
transform:translateZ(0);
* will-change:transform;-
缺点:图层的合成耗运算量
-
实战优化点:
- 1.用translate替代top改变,top会触发layout过程。
- 2.用opacity替代visibility,visibility会触发Repaint。
因为opacity的改变是改变图层的alpha通道,浏览器不知道是否有兄弟节点,可能会影响除了这个dom元素以外的元素,浏览器不能这么做,所以直接会触发整个图层的重绘回流,因此需要创建独立图层,才不会造成重绘回流。
- 4.不要一条一条地修改DOM的样式(每修改一次样式可能会触发一次重绘,因为有缓冲区合并触发),预先定义好class,然后修改DOM的className(一次性修改全部样式)
- 5.把DOM离线后修改,比如:先把DOM给display:none(有一次Reflow),然后把要修改的样式都修改完(但这样修改样式时不会触发重绘和回流),再把它显示出来
- 6.不要把DOM节点的属性值放在一个循环里当作循环里的变量,例如:offsetHeight、offsetWidth。
因为获取属性值需要获取当前真实的DOM的属性,会强制刷新回流的队列缓冲区(用来避免回流过于频繁),必定会触发回流。
-
7.不要使用table布局,可能一个很小的改动会造成整个table的重新布局
-
8.动画实现的速度的选择(动画会触发重绘,不能太过频繁,要根据业务场景寻找平衡点)
-
9.对于动画新建图层
-
10.启用GPU硬件加速。代价是数据都是在CPU上处理的,要用GPU的话,需要数据从CPU通过总线运输到GPU,因此使用GPU的数据不宜过多
-
启动GPU加速的方式:
-
transform:translateZ(0);
* transform:translate3d(0,0,0);
四、浏览器存储
-
1.cookie
-
设计初衷:因为HTTP是无状态请求,所以需要cookie去维持客户端状态。
- httponly:不允许js读写。
- 作用:
-
用于浏览器端和服务器端的交互
* 客户端自身数据的存储- 生成方式:
-
http response header中的set-cookie
* js中通过document.cookie可以读写cookie- 存储限制:
-
作为浏览器存储,大小
4KB左右
* 需要设置过期时间 expire
1
2 1* 缺点:
2
-
cookie是与相关域名绑定的,会造成cdn(不需要携带cookie)的流量损耗。
-
解决方法:cdn的域名与主站的域名要分开。
-
2.localStorage
-
设计初衷:h5专门设计出来用于浏览器存储的。
- 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。
- 大小为5M左右
- 仅在客户端使用,不和服务端进行通信
- 可用来缓存js、css文件
-
3.sessionStorage
-
设计初衷:会话级别的浏览器存储。
- 当用户关闭浏览器窗口后,数据会被删除。
- 大小为5M左右
- 仅在客户端使用,不和服务端进行通信
- 对于表单信息的维护
-
4.IndexedDB
-
设计初衷:用于客户端存储大量结构化数据。
- 基础操作相关链接
- 为应用创建离线版本。
-
5.Service Worker
-
Service Worker 是一个脚本。
- 基础功能相关链接
- Service Worker 可实现在后台运行一些不依赖页面或者用户交互的特性的逻辑。使用 Service Worker 在后台运行同时能和页面通信的能力,去实现大规模后台数据的处理。
- Service Worker 可以拦截和处理网络请求,来管理被缓存的响应,可实现PWA离线应用的能力。
- Service Worker 限制:只有在https协议下才能够被注册,本地调试可用localhost。
- Service Worker 的生命周期:
五、缓存
通过http header来控制缓存策略。本人学习使用的demo
- 1.Cache-Control
http1.1定义的。
强缓存。
通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。
缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。
指令不区分大小写。
各个指令以逗号分隔。
常用的指令:
-
到期时间 指令:
-
max-age=<seconds>
设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。
在缓存期间,浏览器不会向服务端请求资源,直接从缓存中读取资源。
优先级高于expires(http1.0)。
* s-maxage=<seconds>
只对public共享缓存的缓存策略的缓存设备有效(例如:CDN),private的私有缓存无效。
在缓存期间,浏览器向公共缓存区域请求资源(例如:CDN);缓存失效后,CDN才会向源服务器请求更新资源,起到一个
回源的动作。
优先级高于max-age。
1
2 1* **可缓存性 指令:**
2
- private
私有缓存,表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。
* public
共享缓存,表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
* no-cache
发送请求到服务器,去询问验证缓存策略。
* no-store
完全不缓存。
- 2.Expires
http1.0定义的。
强缓存。
响应头包含日期/时间,缓存过期时间,用来指定资源到期时间,是服务端的具体的时间点。
无效的日期,比如 0, 代表着过去的日期,即该资源已经过期。
如果在 Cache-Control 响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。
-
3.Last-Modified / If-Modified-Since
-
基于客户端和服务端协商的缓存机制。
- 语法:Last-Modified/If-Modified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
- Last-Modified —-response header。
-
包含源服务器资源做出修改的日期及时间。
* 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。
* 包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段。
* 精确度比 ETag 要低。- If-Modified-Since —- request header。
-
一个条件式请求首部。
* 服务器只在 Last-Modified的时间 > If-Modified-Since 的时间时才返回资源,返回状态码为 200,且返回资源最后修改的时间 Last-Modified 。
* 如果请求的资源从 If-Modified-Since 的时间起未经修改,那么返回一个不带有消息主体的 304 响应,且 Last-Modified 首部中会带有上次修改时间,然后浏览器从缓存中读取资源。
* 只可以用在 GET 或 HEAD 请求中。- 需要与Cache-Control共同使用。
- Cache-Control缓存时间过期后,才会对 Last-Modified 进行协商。
- 缺点:
-
某些服务端不能获取经精确的修改时间。
* 文件修改时间改了,但是文件内容可能没有变。 -
4.Etag / If-None-Match
-
响应头为资源内容的hash值
- Etag —- response header
-
如果给定URL中的资源更改,则一定要生成新的Etag值。
- If-None-Match —- request header
-
一个条件式请求首部。
* 对于 GET 和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的相匹配的时候,服务端会才返回所请求的资源,响应码为 200 。
* 对于其他方法来说,当且仅当最终确认没有已存在的资源的 ETag 属性值与这个首部中所列出的相匹配的时候,才会对请求进行相应的处理。
* 对于 GET 和 HEAD 方法来说,当验证失败的时候,服务端必须返回响应码 304 (Not Modified,未改变)。对于能够引发服务端状态改变的方法,则返回 412 (Precondition Failed,前置条件失败)。
* 需要注意的是,服务端在生成状态码为 304 的响应的时候,必须同时生成以下会存在于对应的 200 响应中的首部:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary 。- 需要与Cache-Control共同使用。
- 优先级比 Last-Modified / If-Modified-Since 高。