web前端性能优化
web前端的性能优化
性能优化
为什么要做前端优化
先明确一下前端优化的目的是什么 ?
-
从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。
-
从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
页面级别优化
页面级别优化:包含了http请求数以及内联脚本位置优化
1. 减少 HTTP请求数
这一点是最有效的,首先,我们先来了解请求是怎么样的?每个请求都是有成本的,既包含时间成本也包含资源成本。
一个完整的请求都需要经过 DNS寻址、与服务器建立连接、发送数据、等待服务器响应、接收数据这样一个 “漫长” 而复杂的过程。
时间成本就是用户需要看到或者 “感受” 到这个资源是必须要等待这个过程结束的,资源上由于每个请求都需要携带数据,因此每个请求都需要占用带宽。所以请求越多,就会花费更多时间,更多资源,更多宽带。
要怎么优化这个请求次数呢,就有多方面因素影响的了。
1.根据你的网页页面结构,进行针对性优化。
如果你的页面像百度首页一样简单,那么你的请求就会很少。对页面整体结构进行分析,拆分出不同的模块,比如拆分成轮播图、推荐信息列,用户资本信息等等,然后对一些进行合并请求等等。
2.合理设置 HTTP缓存
缓存的力量是强大的,恰当的缓存设置可以大大的减少 HTTP请求。
那么怎样才算合理设置 ?
原则很简单,能缓存越多越好,能缓存越久越好。
例如:
- 很少变化的图片资源可以直接通过 HTTP Header中的Expires设置一个很长的过期头 ;
- 变化不频繁而又可能会变的资源可以使用 Last-Modifed来做请求验证。尽可能的让资源能够在缓存中待得更久。
2.资源合并与压缩
如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。
另外, CSS、 Javascript、Image 都可以用相应的工具进行压缩,压缩后往往能省下不少空间。
图片压缩工具,链接:https://tinypng.com/
能够将图片压缩超过50%,而且画质稍微受一点影响而已。
css压缩工具,链接:https://c.runoob.com/front-end/52
能够将css压缩,极大的减少css的大小。
js压缩工具,链接:https://c.runoob.com/front-end/51
能够将js压缩,极大的减少js的大小。
3.合并 CSS,JS
合并 CSS,减少请求数的又一个好办法。
例如:
你可以写了三个css样式表 css_one.css , css_two.css , css_three.css
这样你就可以写一个主样式style.css 把三个样式表都装进去:
@import “css_one.css”;
@import “css_two.css”;
@import “css_three.css”;
然后你就可以只引用style.css就可以了,这样就能把css合并起来使用,将三个请求变成一个,不过要注意的是,这三个css里面不能出现相同类名。
同样,js也可以用这个方式合并起来。
4.CSS sprite(雪碧图)
通过CSS sprite这种办法把几张图片合并成一个,然后通过容器剪切出对应的图片。这种办法特别的好,往往能把十多个图片请求变成一个,优化率1000%多
5.图片懒加载
就是只把首屏的图片加载出来,还没浏览到的部分不加载,等你滑动看到它的时候再加载出来。
这种优化技巧特别普遍,淘宝,美团等等都是有用到这种优化。极大的加快了首屏加载速度,提高了用户体验。
lazy load网址:https://www.lazyloadjs.cn/
6.将 CSS放在 head中,js放在尾部
如果将 CSS放在其他地方比如div中,则浏览器有可能还未下载和解析到 CSS就已经开始渲染页面了,这就导致页面由无 CSS状态跳转到 CSS状态,用户体验比较糟糕。
除此之外,有些浏览器会在 CSS下载完成后才开始渲染页面,如果 CSS放在靠下的位置则会导致浏览器将渲染时间推迟。
而js和dom页面渲染公用一个线程,如果把js放在前面的话,可能会阻塞住页面的渲染,导致dom渲染不出来(白屏时间长),用户体验极差。
代码级别优化
代码级别的优化:包含DOM操作优化,CSS选择符优化以及图片优化等
1.对dom的操作
在脚本中 document.images()、document.forms() 、getElementsByTagName()
返回的都是 HTMLCollection类型的集合,在平时使用的时候大多将它作为数组来使用,因为它有 length属性,也可以使用索引访问每一个元素。
当你需要遍历 HTML Collection的时候,尽量将它转为数组后再访问,以提高性能。即使不转换为数组,也请尽可能少的访问它,例如在遍历的时候可以将 length属性、成员保存到局部变量后再使用局部变量。
例如:
var x = getElementsByTagName('div')
var y = []
funtion deepclone() {
//深克隆
return object
}
for(let i = 0; i<x.length; i++) {
y.push(deepclone(x[i]))
}
2.慎用 with
with(obj){
p = 1
};
代码块的行为实际上是修改了代码块中的 执行环境 ,将obj放在了其作用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,如果没有再依次按作用域链向上查找,因此使用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。
3.减少作用域链查找
如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的,严重影响效率。
低效率的写法:
// 全局变量
var globalVar = 1;
function myCallback(info){
for( var i = 100000; i--;){
//每次访问 globalVar 都需要查找到作用域链最顶端,本例中需要访问 100000 次
globalVar += i;
}}
更高效的写法:
// 全局变量
var globalVar = 1;
function myCallback(info){
//局部变量缓存全局变量
var localVar = globalVar;
for( var i = 100000; i--;){
//访问局部变量是最快的
localVar += i;
}
//本例中只需要访问 2次全局变量在函数中只需要将 globalVar中内容的值赋给localVar 中区
globa
lVar = localVar;
}
此外,要减少作用域链查找还应该减少闭包的使用。
4.字符串拼接
我们学会,字符串是可以用+进行拼接的,但是这种性能很低,他的过程就是,重新开辟一个内存,然后拼接起来后复制给原来的字符串。
其实我们可以直接使用join(),
直接把字符串拼接起来。
5.按需引入
const Recommend = () => import(/* webpackChunkName: "recommend" */ 'components/recommend/recommend')
const Singer = () => import(/* webpackChunkName:'singer' */ 'components/singer/singer')
const Rank = () => import(/* webpackChunkName:'rank' */ 'components/rank/rank')
const Search = () => import(/* webpackChunkName:'search' */ 'components/search/search')
const SingerDetail = () => import(/* webpackChunkName:'singer' */ 'components/singer-detail/singer-detail')
const Disc = () => import(/* webpackChunkName:'disc' */ 'components/disc/disc')
const TopList = () => import(/* webpackChunkName:'toplist' */ 'components/top-list/top-list')
const UserCenter = () => import(/* webpackChunkName:'user' */ 'components/user-center/user-center')
这样子写,就能够提高首屏速度,在需要的时候再import,能够提高性能。
上一篇: PHP初学者头疼问题总结_php基础
下一篇: Python压缩和解压缩zip文件