web前端性能优化,终极武功秘籍(建议收藏),太棒了

导语:
前几天发了一个前端优化的办法,看的人还挺多的,于是马上把它们深度总结一下,也方便以后自己翻阅学习。

一位优秀的前端工程师都必须懂得的前端优化技巧,你会几个?

前端优化是复杂的,针对方方面面的资源都有不同的方式。
我们先来明确一下前端优化的目的是什么 ?

1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。

2. 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。

接着,前端性能优化可以分为两大类分别是:

  • 页面级别优化,包含了http请求数以及内联脚本位置优化,
  • 代码级别的优化,包含DOM操作优化,CSS选择符优化以及图片优化等

这里写目录标题

  • 一,页面级别优化
  • 1. 减少 HTTP请求数3,资源合并与压缩4,合并 CSS,js。5,CSS sprite(雪碧图)6,图片懒加载7,将 CSS放<typo id="typo-419" data-origin="在" ignoretag="true">在</typo> head中,js放在尾部
  • 二,代码级别的优化
  • 1,对dom的操作2,慎用 with3,减少作用域链查找4,字符串拼接5,需要的时候<typo id="typo-488" data-origin="在" ignoretag="true">在</typo>引入

一,页面级别优化

1. 减少 HTTP请求数

这一点是最有效的,首先,我们先来了解请求是怎么样的?每个请求都是有成本的,既包含时间成本也包含资源成本。

一个完整的请求都需要经过 DNS寻址、与服务器建立连接、发送数据、等待服务器响应、接收数据这样一个 “漫长” 而复杂的过程。(如下图)

image

时间成本就是用户需要看到或者 “感受” 到这个资源是必须要等待这个过程结束的,资源上由于每个请求都需要携带数据,因此每个请求都需要占用带宽。所以请求越多,就会花费更多时间,更多资源,更多宽带。

至于你要怎么优化这个请求次数呢,这就是多方面因素影响的了。

  1. 根据你的网页页面结构,进行针对性优化。

如果你的页面像百度首页一样简单,那么你的请求就会很少。对页面整体结构进行分析,拆分出不同的模块,比如拆分成轮播图、推荐信息列,用户资本信息等等,然后对一些进行合并请求等等。

  1. 合理设置 HTTP缓存

缓存的力量是强大的,恰当的缓存设置可以大大的减少 HTTP请求。以首页为例,当浏览器没有缓存的时候访问一共会发出 205个请求,共 3M数据 (如下图)

image

而当第二次访问即浏览器已缓存之后访问则仅有 31个请求,共 280多 K数据 (如下图)。

image

那么怎样才算合理设置 ?原则很简单,能缓存越多越好,能缓存越久越好。例如:

1. 很少变化的图片资源可以直接通过 HTTP Header中的Expires设置一个很长的过期头 ; 2. 变化不频繁而又可能会变的资源可以使用 Last-Modifed来做请求验证。尽可能的让资源能够在缓存中待得更久。

3,资源合并与压缩

如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。另外, CSS、 Javascript、Image 都可以用相应的工具进行压缩,压缩后往往能省下不少空间。

image

图片压缩工具,链接:https://tinypng.com/,能够将图片压缩超过50%,而且画质稍微受一点影响而已。

image

css压缩工具,链接:https://c.runoob.com/front-end/52,能够将css压缩,极大的减少css的大小。

image

js压缩工具,链接:https://c.runoob.com/front-end/51,能够将js压缩,极大的减少js的大小。

4,合并 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也可以用这个方式合并起来。

5,CSS sprite(雪碧图)

image

通过这种办法把几张图片合并成一个,然后通过容器剪切出对应的图片。

这种办法特别的好,往往能把十多个图片请求变成一个,优化率1000%多,可以说是终极技能了,快快学会吧。

6,图片懒加载

就是只把首屏的图片加载出来,还没浏览到的部分不加载,等你滑动看到它的时候再加载出来。

这种优化技巧特别普遍,淘宝,美团等等都是有用到这种优化。极大的加快了首屏加载速度,提高了用户体验。

image

lazy load网址:https://www.lazyloadjs.cn/

7,将 CSS放在 head中,js放在尾部

如果将 CSS放在其他地方比如body中,则浏览器有可能还未下载和解析到 CSS就已经开始渲染页面了,这就导致页面<typo id="typo-2117" data-origin="由" ignoretag="true">由</typo><typo id="typo-2118" data-origin="无 " ignoretag="true">无 </typo>CSS状态跳转到 CSS状态,用户体验比较糟糕。(也就是平时我们看到的乱屏,过了一两秒后布局才正常)

除此之外,有些浏览器会在 CSS下载完成后才开始渲染页面,如果 CSS放在靠下的位置则会导致浏览器将渲染时间推迟。

而js和dom页面渲染<typo id="typo-2242" data-origin="公用" ignoretag="true">公用</typo>一个线程,如果把js放在前面的话,可能会阻塞住页面的渲染,导致dom渲染不出来(白屏时间长),用户体验极差。

二,代码级别的优化

1,对dom的操作

在脚本中 document.images()、document.forms() 、getElementsByTagName()返回的都是 HTMLCollection类型的集合,在平时使用的时候大多将它作为数组来使用,因为它有 length属性,也可以使用索引访问每一个元素。

不过它可不是一个数组,在访问性能上则比数组要差很多,原因是这个集合并不是一个静态的结果,它表示的仅仅是一个特定的查询,每次访问该集合时都会重新执行这个查询从而更新查询结果。所谓的 “访问集合” 包括读取集合的 length属性、访问集合中的元素。

因此,当你需要遍历 HTML Collection的时候,尽量将它转为数组后再访问,以提高性能。即使不转换为数组,也请尽可能少的访问它,例如在遍历的时候可以将 length属性、成员保存到局部变量后再使用局部变量。

例如:

<pre language="javascript" code_block="true">var x = getElementsByTagName('div')
var y = []
funtion deepclone() {
    //深克隆
    return object
}
for(let i = 0; i<x.length; i++) {
    y.push(deepclone(x[i]))
}
123456789</pre>

# 2,慎用 with

<pre language="javascript" code_block="true"> with(obj){ 
    p = 1
 };
123</pre>

代码块的行为实际上是修改了代码块中的 执行环境 ,将obj放在了其作用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,如果没有再依次按作用域链向上查找,因此使用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。

因此,除非你能肯定在 with代码中只访问 obj中的属性,否则慎用 with,替代的可以使用局部变量缓存需要访问的属性。

3,减少作用域链查找

前文谈到了作用域链查找问题,这一点在循环中是尤其需要注意的问题。如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的,严重影响效率。

低效率的写法:

<pre language="javascript" code_block="true">// 全局变量 
var globalVar = 1; 
function myCallback(info){    
    for( var i = 100000; i--;){       
    //每次访问 globalVar 都需要查找到作用域链最顶端,本例中需要访问 100000 次       
    globalVar += i;    
}}   
1234567</pre>

更高效的写法:

<pre language="javascript" code_block="true">   // 全局变量 
var globalVar = 1; 
function myCallback(info){    
    //局部变量缓存全局变量     
    var localVar = globalVar;    
    for( var i = 100000; i--;){       
    //访问局部变量是最快的        
    localVar += i;    
    }    
//本例中只需要访问 2次全局变量在函数中只需要将 globalVar中内容的值赋给localVar 中区   
    globalVar = localVar; 
}  
123456789101112</pre>

此外,要减少作用域链查找还应该减少闭包的使用。

4,字符串拼接

我们学会,字符串是可以用+进行拼接的,但是这种性能很低,<typo id="typo-3834" data-origin="他" ignoretag="true">他</typo>的过程就是,重新开辟一个内存,然后拼接起来后复制给原来的字符串。

其实我们可以直接使用join(),直接把字符串拼接起来。

5,需要的时候在引入

<pre language="javascript" code_block="true">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')
12345678</pre>

这样子写,就能够提高首屏速度,在需要的时候再import,能够提高性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351