一、网页优化
1、静态资源压缩
借助构建工具(webpack、gulp)适当压缩图片、脚本及样式等网页静态资源。
2、CSS雪碧图、base64内联图片
将站内小图标合并成一张图,使用css定位截取对应图标;适当使用内联图片。
3、样式置顶、脚本置底
页面是一个逐步呈现的过程,样式置顶能更快呈现页面给用户;
4、使用外链的css和js
多个页面引用公共静态资源,资源复用减少额外的http请求。
5、避免空src的img标签
空src的图片依然会发起http请求。
6、避免在HTML中缩放图片
图片尽量按需求使用指定规格的尺寸,而不是加载一张大图片再将它缩小。
7、<link>
标签prefetch预加载
将link
标签的rel
属性设置为prefetch
,可以让浏览器在主渲染机制介入前就预加载资源。这种机制可以更早的获取资源且不阻塞页面的初始化。
<link rel="prefetch" href="./style.css" as="style">
也可以指定as的类型加载不同类型的资源。
style
script
video
audio
image
font
document
…
8、关于CSS
(1)选择器使用经验:
优先选择类选择器,可替代多层标签选择器;
慎用ID选择器,虽然它效率高,但是在页面中是唯一的,不利于团队协作和维护;
合理利用选择器的继承性;
避免css表达式。
(2)减少选择器的层级:
应尽量避免多层次的选择器嵌套,最好不要超过3层。
(3)精简页面样式文件,去掉不用的样式:
浏览器会进行多余的样式匹配,影响渲染时间,另外样式文件过大也会影响加载速度。
(4)利用css继承减少代码量:
利用css的可继承属性,父元素设置了样式,子元素就不用再设置。
常见的可以继承的属性比如:color,font-size,font-family等;不可继承的比如:position,display,float等。
二、JavaScript 优化
1、使用事件委托
给多个同类DOM元素绑定事件使用事件委托。
<ul id="container">
<li class="list">1</li>
<li class="list">2</li>
<li class="list">3</li>
</ul>
// 不合理的方式:给每个元素都绑定click事件
$('#container .list').on('click', function() {
var text = $(this).text();
console.log(text);
});
// 事件委托方式:利用事件冒泡机制将事件统一委托给父元素
$('#container').on('click', '.list', function() {
var text = $(this).text();
console.log(text);
});
使用事件委托除了性能上更优,动态创建的DOM元素也不需要再绑定事件。
2、图片预加载和懒加载
(1)基于用户行为的预加载
对于用户行为可能进行的操作进行判断,预先加载将来可能需要用到的资源。
比如:
- 当用户在搜索输入框输入时,预先加载搜索结果页可能用到的资源;
- 当用户去操作一个Tab选项卡时,默认显示其中一个,当要去点击(click)其他选项时,在鼠标hover时,就可先加载将来会用到的资源;
(2)懒加载
除页面初始化需要的内容或组件之外,其他都可以延迟加载,如剪切图片的js库、不在可视范围的图片等等。
图片懒加载(判断图片是否在可视区域范围内,若在,则将真实路径赋给图片)
3、减少全局变量的使用
任何一个非局部变量在函数中被使用超过一次时,都应该将其存储为局部变量。以避免全局查找。
注意:在javascript代码中,任何没有使用var声明的变量都会变为全局变量,不正当的使用会带来性能问题。
4、避免不必要的属性查询
使用变量和数组要比访问对象上的属性更有效率,因为对象必须在原型链中对拥有该名称的属性进行搜索。一次两次的属性查找不会造成性能问题,但若需要多次查找,如在循环中,就会影响性能。
为了避免不必要的属性查找,可以将常用的对象属性缓存为变量:
比如:
var url = window.location.href;
var query = url.substring(url.indexOf("?"));
5、使用函数节流
假设有一个搜索框,给搜索框绑定onkeyup
事件,这样每次鼠标抬起都会发送请求。而使用节流函数,能保证用户在输入时的指定时间内的连续多次操作只触发一次请求。
比如:
<input type="text" id="input" value="" />
// 绑定事件
document.getElementById('input').addEventListener('keyup', function() {
throttle(search);
}, false);
// 逻辑函数
function search() {
console.log('search...');
}
// 节流函数
function throttle(method, context) {
clearTimeout(method.tId);
method.tId = setTimeout(function() {
method.call(context);
}, 300);
}
节流函数的应用场景不局限搜索框,比如页面的滚动onscroll
,拉伸窗口onresize
等都应该使用节流函数提升性能。
6、减少回流和重绘
在浏览器渲染过程中,涉及到回流和重绘,这是一个损耗性能的过程,应注意在脚本操作时减少会触发回流和重绘的动作。
- 回流:元素的几何属性发生了变化,需要重新构建渲染树。渲染树发生变化的过程,就叫回流;
- 重绘:元素的几何尺寸没有变化,某个元素的CSS样式(背景色或颜色)发生了变化。
触发重排和重绘的操作有哪些?
调整窗口大小
修改字体
增加或者移除样式表
内容变化,比如用户在框中输入文字
操作class属性
脚本操作DOM(增加、删除或修改DOM元素)
计算offsetWidth和offsetHeight属性
设置style属性的值
如何减少重排和重绘,提升网页性能?
- 脚本操作DOM元素
将DOM元素设置为display:none
,设置过程中会触发一次回流,但之后可以随意改动,修改完后再显示;
将元素clone到内存中再进行操作,修改完后重新替换元素。
- 修改元素的样式
尽量批量修改,而不是逐条修改;
使用class批量修改代替style直接修改。
-
为元素添加动画时将元素CSS样式设为
position:fixed
或position:absolute
,元素脱离文档流后不会引起回流。 -
在调整窗口大小、输入框输入、页面滚动等场景时使用节流函数(上面已提到过)。
三、HTTP
合理设置浏览器缓存。
强缓存和协商缓存
缓存的类型强缓存和协商缓存。两者区别是,强缓存不会向服务器发请求,而协商缓存会发请求,匹配成功返回304 Not Modified,匹配不成功返回200;浏览器会先校验强缓存,若强缓存未命中,再进行协商缓存校验。
如何配置浏览器缓存?
- 在
web
服务器的返回响应中添加Expires
和Cache-Control
; - 在
nginx
或apache
的配置文件中配置Expires
和Cache-Control
。