上一篇我们已经围绕“网络层面”探索页面性能优化的方案,接下来本篇围绕“浏览器渲染层面”继续开展探索。正文开始前,我们思考如下问题:
- 浏览器渲染页面会经过哪几个关键环节?“渲染层面”的优化从哪几方面着手?
- “渲染层面”的性能优化方案会有哪些?
我们了解“页面渲染关键环节”后,便可知晓影响页面渲染性能的因素主要是静态资源:HTML、CSS、JS、图片等。因此“渲染层面”的性能优化方案主要就是围绕静态资源展开探索,其方案制定可围绕下面2个原则展开:
- 在线压缩,例如CSS Minify
- webpack压缩插件
<head>
里,尽早地进行样式解析,构建CSSOM 树可继承属性:
- 所有元素可继承:visibility 和 cursor。
- 内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction。
- 块元素可继承:text-indent和text-align。
- 列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。
- 表格元素可继承:border-collapse。
总结:CSS继承特性主要是指文本方面的继承,而关于与盒模型相关的属性不支持继承。
localStorage
/sessionStorage
/IndexedDB
等DOM
对象等loader
开启 cache
缓存<body>
底部,让JS不阻塞HTML和CSS的解析// 1. 正常模式
<script src="index.js"></script>
// 2. async 模式(异步执行)
<script async src="index.js"></script>
// 3. defer 模式(延迟执行)
<script defer src="index.js"></script>
一般当我们的脚本与 DOM 元素和其它脚本之间的依赖关系不强时,我们会选用 async;当脚本依赖于 DOM 元素时,我们会选用 defer。(合理选择 script 加载模式,可以有效地提升性能)
requestAnimationFrame 按照浏览器的刷新率(60Hz左右)来调动动画帧,从而实现更加流畅和高性能的动画效果。
简介和特性 | 是否支持透明 | 支持颜色种数 | 压缩方式 | 浏览器兼容性 | 适用场景 | |
---|---|---|---|---|---|---|
jpg | - 最常见、应用最广泛的图片格式 - 体积一般,通常小于 png, gif 等格式 | 不支持透明 | 约1600万种颜色 | 有损压缩 | 几乎所有浏览器都支持 | 呈现色彩丰富的图片,比如大背景图、轮播图或Banner图等 |
png8 | - 一种无损压缩的高保真的图片格式 - 8位的png,体积较大 | 支持透明 | 256种(2^8) | 无损压缩 | 几乎所有浏览器都支持 | 呈现小图片,比如小Logo、颜色简单对比强烈小图标 |
png24 | - 一种无损压缩的高保真的图片格式 - 24位的png,体积较大 | 不支持透明 | 约1600万种颜色 | 无损压缩 | 几乎所有浏览器都支持 | 呈现颜色较多的图片,比如背景图 |
png32 | - 一种无损压缩的高保真的图片格式 - 32位的png,体积大 | 支持半透明(8位透明通道) | 2^32种 | 无损压缩 | 几乎所有浏览器都支持 | 呈现色彩丰富高清图片,比如海报 |
svg | - 矢量图,任意缩放不影响清晰度 - 体积视内容而定 | 支持设置透明度 | RGB/RGBA/十六进制设置颜色 | 支持有损和无损压缩 | Chrome 4 (2010年1月发布)以上版本支持 caniuse.com/svg | 适用任意缩放不失真的场景 |
gif | - 支持动态图片 - 压缩率较高 - 体积较小 | 支持透明 | 256种(2^8) | 无损压缩 | Chrome 58(2017年6月发布)以上版本支持 caniuse.com/gif | 适用于色彩较少的动图 |
webp | - 支持动态图片 - 压缩率较高 - 体积较小 | 支持透明 | 约1600万种颜色 | 有损和无损压缩 | Chrome 32(2014年1月发布)以上版本支持,兼容性不太好 caniuse.com/webp | 兼容性要求不高的多种图片格式场景 |
图片列表一般采用懒加载进行按需加载,滚屏时当图片已将出现在可视区域的时候进行加载。(有效地减轻服务器批量加载图片的压力)
let imgList = [...document.querySelectorAll('img')];
let len = imgList.length;
const lazyLoad = (function(){
let count = 0;
return function() {
let deleteIndexList = [];
imgList.forEach((img,index)=> {
let rec = img.getBoundingClientRect();
if(rec.top < window.innerHeight) {// 元素出现在可视区(window.innerHeight:可视窗口的高度)
img.src = img.dataset.src; // 将data-src设置成图片src
deleteIndexList.push(index);
count++;
if(count === len) {// 当图片都加载完,移除滚动监听事件
document.removeEventListener('scroll', lazyLoad)
}
}
})
imgList = imgList.filter((img, index)=> !deleteIndexList.includes(index))
}
})()
// 节流函数
const throttle = function(fn, timing = 500) {
let prev = 0
return function() {
let now = +new Date();
if(now - prev > timing) {
prev = now;
fn.apply(this, arguments)
}
}
}
// 滚动监听加上节流控制
const _throttle = throttle(lazyLoad)
document.addEventListener('scroll', _throttle)
预加载preload,在大图片加载完成前先加载小的loading,用于提升用户体验。(该优化思想不仅可以用于图片加载,也能用于异步请求、html标签预加载)
// 创建 img 图片元素
const myImage = (function(){
let imgNode = document.createElement('img')
document.body.appendChild( imgNode )
return {
setSrc: function(src) {
imgNode.src = src
}
}
})()
/**
* 预加载
*/
const preLoad = (function(){
let img = new Image();
img.onload = function() {
myImage.setSrc( this.src )// this指向img
}
return {
setImg: function(src) {
myImage.setSrc('./img/loading.gif')
img.src = src
}
}
})()
preLoad.setImg('./img/bg_gaoqing.jpeg')
.bg {
/* 正常(未缩小屏幕)加载大尺寸图片 */
background-image:?url('img_flowers.jpg');
}
/* 当屏幕宽度小于400 */
@media screen and (max-width: 400px)?{
.bg {
background-image:?url('img_smallflower.jpg');
}
}
<picture>
<source srcset="img_smallflower.jpg" media="(max-width: 400px)">
<img src="img_flowers.jpg" alt="Flowers">
</picture>