在讲前端性能优化前,先了解下一个网站在浏览器端是如何渲染的
1、首先输入url地址
2、浏览器根据url向服务器发送http请求
3、服务器端接收请求并返回html代码返回浏览器
4、浏览器接收html代码并解析生成页面
5、解析页面过程
a、HTML文档生成DOM和CSS生成CSSOM
b、DOM和CSSOM生成RenderTree
c、有了RenderTree知道了浏览器中有那些节点,各个节点的CSS定义绘制成layout render tree
d、有了layout render tree 浏览器使用浏览器UI绘制每个节点生成 paint render tree
资源的合并和压缩
减少http请求,减少请求资源的大小
html压缩
html压缩是压缩文本中空格,制表符,换行符,注释等
css压缩
无效代码删除
代码合并
js的压缩和混乱
无效字符删除,注释
代码语义的缩减和优化
代码保护
文件合并
减少http请求
问题
首屏加载慢
缓存失效问题
方案
公共库合并
不同页面的合并
开启gzip
图片先关优化
png8/png24/png32之间的区别
png8 支持透明,文件大小小
png24 不支持透明
png32 支持透明
图片压缩
针对真实图片情况,舍弃一些相对无关紧要的色彩信息
CSS雪碧图
把一些图片整合到一张单独的图片中->减少网站http请求数量
缺点:整合图片比较大,一次加载比较慢
方案:保证雪碧图资源不要太大
Image inline
将图片的内容内嵌到html当中->减少网站http请求
只适合小图片,不适合大图片
矢量图
使用SVG进行适量图的绘制
使用iconfont解决icon问题
只适合简单图片,不适合复杂图片
webp
webp有更优的图像数据算法,能带来更小的图片体积
目前只有安卓能用
不同格式图片常用的业务场景
jpg有损压缩,压缩率高,不支持透明
png支持透明
webp压缩程度更好,但是只适合安卓
svg矢量图,代码内嵌,只适合图片相对简单的场景
压缩网站
页面加载和渲染
前面讲了解析页面的过程。页面解析过程的特点
顺序执行
词法分析的顺序是从上到下->页面DOM,JS资源,CSS资源从上到下
并发加载
web中资源是并发加载
是否阻塞
css阻塞
css head中阻塞页面的渲染
页面出现闪动。
这个页面要呈现相应的效果,需要等待link对应的css加载完毕才会渲染,所以整个渲染是带样式的
css阻塞js的执行
css在加载完之前后续的js会被阻塞
css不阻塞外部脚本的加载
css不阻塞外部脚本的加载但是阻塞执行,因为js可能会操作DOM,在操作DOM的之前必须等待CSS执行完毕
js阻塞
直接引入的js阻塞页面的渲染
js document.write可能会修改文档结构,js代码的执行会阻塞后面节点的创建
js不阻塞资源的加载
预先扫描器会对后续资源加载
js顺序执行,阻塞后续js逻辑的执行
js执行时单线程
依赖关系
页面的渲染依赖于css的加载
页面必须等待DOM和CSSOM的加载,才会去生成RenderTree,推荐把css放到head中,这样不会出现页面闪动问题
js执行顺序的依赖关系
需要关注js在加载关系是否有依赖关系
js逻辑对于dom逻辑的依赖关系
引入方式
css
link
@import
js
script
阻塞问题
defer
在文档渲染完毕,在DOMContentLoaded之前调用执行
是顺序执行,不会阻塞页面加载
async
js异步加载,不会阻塞页面加载,放弃js直接的依赖关系
js资源动态引入
代码实战
一个简单的引入js代码
<!DOCTYPE html> <html> <head> <script src="a.js" defer></script> <script src="b.js" defer></script> <script> window.addEventListener('DOMContentLoaded', function(){ console.log('DOMContentLoaded') }) </script> </head> <body> <p>js加载</p> </body> </html>
script
图片结果可以看出a.js,b.js阻塞页面的渲染
defer
图片结果可以看出a.js,b.js不阻塞页面加载,看出defer执行是在页面渲染完毕和DOMContentLoaded之间执行
async
图片结果可以看出a.js,b.js不阻塞页面加载,但是在DOMContentLoaded并不会影响async的加载
加载和执行优化
css样式表置顶
js脚本置底
合理使用js异步加载能力
懒加载
图片进入可视区域之后请求图片资源
减少无效资源的加载
并发加载的资源过多会阻塞js的加载
预加载
静态资源在使用之前提前进行请求
提升用户体验
重绘和回流
css性能让js变慢
css放在head中,在加载css时,会阻塞整个页面渲染,js代码执行时,页面渲染也是阻塞的
回流
当RenderTree中的一部分因为元素的规模尺寸,布局,隐藏等改变而且需要重新构建。称为回流
当页面布局和几何属性改变时就需要回流
重绘
当RenderTree中的一些元素需要更新属性,而这些只是影响元素的外观,风格,而不会影响布局的,比如background-color。称为重绘。
触发页面重布局的属性
盒子模型相关属性会触发重布局
width/height/padding/margin/display/border-width/border/min-height
定位属性及浮动也会触发重布局
top/bottom/left/right/position/float/clear
改变节点内部文字结构也会触发重布局
text-align/overflow-y/font-weight/overflow/font-family/vertival-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
优化点
translate替代top
opacity替换visibility
预先定义好class,然修改DOM的className
把DOM离线后修改,比如把DOM设置display:none,最后在显示出来
不要把DOM节点的属性值放在一个循环里当成循环里的变量 offsetHeight,offsetWidth
不要使用table布局
动画实现的速度的选择
启动GPU硬件加速 transform:translateZ(0)
浏览器存储
cookie
用于浏览器和服务器之间交互
客户端自身数据存储
限制
存储大小只有4kb
sessionStorage
localStorage
HTML5设计出来专门用于浏览器存储
存储大小5M
缓存
服务器端性能优化