前端性能优化方案都有哪些?

2023-06-16 0 827

一、网页级强化

  1. 增加 HTTP允诺数

这条思路大体上所有后端人都知道,而且也是最重要最有效的。都说要增加 HTTP允诺,那允诺多了到底会怎么样呢 ?首先,每一允诺都是有生产成本的,既包涵天数生产成本也包涵资源生产成本。两个完整的允诺都须要经过 DNS串行、与伺服器建立相连、发送统计数据、等候伺服器积极响应、接收统计数据这种两个 “艰难” 而复杂的操作过程。天数生产成本就是采用者须要看见或者 “感受” 到那个天然资源是必须要等候那个过程结束的,天然资源上虽然每一允诺都须要随身携带统计数据,因而每一允诺都须要挤占频宽。另外,虽然应用程序进行mammalian允诺的允诺四元组有下限的 (具体内容参看该处 ),因而允诺班莱班县了以后,应用程序须要科孔允诺,因而会增加采用者的等候天数,会给采用者造成公交站点速度快这种两个第一印象,即使可能采用者能看见的第一屏的天然资源都已经允诺完了,但是应用程序的unlock会一直存在。

  增加 HTTP允诺数的主要有效途径包括:

  (1). 从设计实现微观精简网页

假如你的网页像腾讯主页那样单纯,那么接下去的规则大体上都并不需要了。保持网页简约、增加天然资源的采用时最间接的。假如不是这种,你的网页须要绚丽的皮肤,则继续阅读下面的内容。

  (2). 科学合理增设 HTTP内存

内存的力量是强大的,正确的内存增设能小小的增加 HTTP允诺。短果啊主页为例,当应用程序没有内存的时候出访总共会发出 78个允诺,共 600多 K统计数据 (如图 1.1),而当第二次出访即应用程序已内存之后出访则仅有 10个允诺,共 20多 K统计数据 (如图 1.2)。 (这里须要说明的是,假如间接 F5创下网页的话效果是不那样的,这种情况下允诺数还是那样,不过被内存天然资源的允诺伺服器是 304积极响应,只有 Header没有Body ,能节约频宽 )

怎样才算科学合理增设 ?原则很单纯,能内存圣埃卢瓦,能内存Porcheresse好。例如,很少变动的图片天然资源能间接通过 HTTP Header中的Expires增设两个极短的已过期头 ;变动不频密而又可能会变的天然资源能采用 Last-Modifed来做允诺校正。尽量的让天然资源能够在内存中待得更久。有关 HTTP内存的具体内容增设和原理该处就不再详细描述了,有兴趣的能参照以下文章:

HTTP1.1协议中有关内存思路的描述

Fiddler HTTP Performance中有关内存的介绍

  (3). 天然资源合并与填充

假如能的话,尽量的将外部的脚本、样式进行合并,多个合为两个。另外, CSS、 Javascript、Image 都能用相应的工具进行填充,填充后往往能省下不少空间。

  (4). CSS Sprites

  合并 CSS图片,增加允诺数的又两个好办法。

(5). Inline Images

采用 data: URL scheme的方式将图片嵌入到网页或 CSS中,假如不考虑天然资源管理上的问题的话,不失为两个好办法。假如是嵌入网页的话换来的是增大了网页的体积,而且无法利用应用程序内存。采用在 CSS中的图片则更为理想一些。

 (6). Lazy Load Images(自己对这一块的内容还是不了解)

这条思路实际上并不一定能增加 HTTP允诺数,但是却能在某些条件下或者网页刚加载时增加 HTTP允诺数。对于图片而言,在网页刚加载的时候能只加载第一屏,当采用者继续往后滚屏的时候才加载后续的图片。这种一来,假如采用者只对第一屏的内容感兴趣时,那剩余的图片允诺就都节约了。曾经的做法是在加载的时候把第一屏之后的图片地址内存在 Textarea标签中,待采用者往下滚屏的时候才 “惰性” 加载。

 2. 将外部脚本置底(将脚本内容在网页信息内容加载后再加载)

前文有谈到,应用程序是能mammalian允诺的,这一特点使得其能够更快的加载天然资源,然而外链脚本在加载时却会阻塞其他天然资源,例如在脚本加载完成之前,它后面的图片、样式以及其他脚本都处于阻塞状态,直到脚本加载完成后才会开始加载。假如将脚本放在比较靠前的位置,则会影响整个网页的加载速度从而影响采用者体验。解决这一问题的方法有很多,而最单纯可依赖的方法就是将脚本尽量的往后挪,增加对mammalian下载的影响。

3. 异步执行 inline脚本(其实原理和上面是那样,保证脚本在网页内容后面加载。)

inline脚本对性能的影响与外部脚本相比,是有过之而无不及。主页,与外部脚本那样, inline脚本在执行的时候那样会阻塞mammalian允诺,除此之外,虽然应用程序在网页处理方面是单线程的,当 inline脚本在网页渲染之前执行时,网页的渲染工作则会被推迟。简而言之, inline脚本在执行的时候,网页处于空白状态。鉴于以上两点原因,建议将执行天数较长的 inline脚本异步执行,异步的方式有很多种,例如采用 script元素的defer 属性(存在兼容性问题和其他一些问题,例如不能采用 document.write)、采用setTimeout ,此外,在HTML5中引入了 Web Workers的机制,恰恰能解决此类问题。

 4. Lazy Load Javascript(只有在须要加载的时候加载,在一般情况下并不加载信息内容。)

随着 Javascript框架的流行,越来越多的公交站点也使用起了框架。不过,两个框架往往包括了很多的功能实现,这些功能并不是每两个网页都须要的,假如下载了不须要的脚本则算得上是一种天然资源浪费 -既浪费了频宽又浪费了执行花费的天数。目前的做法大概有两种,一种是为那些流量特别大的网页专门定制两个专用的 mini版框架,另一种则是 Lazy Load。YUI 则采用了第二种方式,在 YUI的实现中,最初只加载核心模块,其他模块能等到须要采用的时候才加载。

5. 将 CSS放在 HEAD中

假如将 CSS放在其他地方比如 BODY中,则应用程序有可能还未下载和解析到 CSS就已经开始渲染网页了,这就导致网页由无 CSS状态跳转到 CSS状态,采用者体验比较糟糕。除此之外,有些应用程序会在 CSS下载完成后才开始渲染网页,假如 CSS放在靠下的位置则会导致应用程序将渲染天数推迟。

 6. 异步允诺 Callback(就是将一些行为样式提取出来,慢慢的加载信息的内容)

在某些网页中可能存在这种一种需求,须要采用 script标签来异步的允诺统计数据。类似:

Javascript: /*Callback 函数*/ function myCallback(info){ //do something here }

  HTML:

  cb返回的内容 :

myCallback(Hello world!);

像以上这种方式间接在网页上写 <script>对网页的性能也是有影响的,即增加了网页首次加载的负担,推迟了 DOMLoaded和window.onload 事件的触发时机。假如时效性允许的话,能考虑在 DOMLoaded事件触发的时候加载,或者采用 setTimeout方式来灵活的控制加载的时机。

 7. 增加不必要的 HTTP跳转

对于以目录形式出访的 HTTP链接,很多人都会忽略链接最后是否带 ’/,假如你的伺服器对此是区别对待的话,那么你也须要注意,这其中很可能隐藏了 301跳转,增加了多余允诺。具体内容参看下图,其中第两个链接是以无 ’/结尾的方式出访的,于是伺服器有了一次跳转。

  8. 避免重复的天然资源允诺

这种情况主要是虽然疏忽或网页由多个模块拼接而成,然后每一模块中允诺了同样的天然资源时,会导致天然资源的重复允诺

  二、代码级强化

  1. Javascript

  (1). DOM

DOM操作应该是脚本中最耗性能的一类操作,例如增加、修改、删除 DOM元素或者对 DOM集合进行操作。假如脚本中包涵了大量的 DOM操作则须要注意以下几点:

a. HTML Collection(HTML收集器,返回的是两个数组内容信息)

在脚本中 document.images、document.forms 、getElementsByTagName()返回的都是 HTMLCollection类型的集合,在平时采用的时候大多将它作为数组来采用,因为它有 length属性,也能采用索引出访每两个元素。不过在出访性能上则比数组要差很多,原因是那个集合并不是两个静态的结果,它表示的仅仅是两个特定的查询,每次出访该集合时都会重新执行那个查询从而更新查询结果。所谓的 “出访集合” 包括读取集合的 length属性、出访集合中的元素。

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

 b. Reflow & Repaint

除了上面一点之外, DOM操作还须要考虑应用程序的 Reflow和Repaint ,因为这些都是须要消耗天然资源的,具体内容的能参照:

如何增加应用程序的 repaint和 reflow?

 (2). 慎用 with

with(obj){ p = 1}; 代码块的行为实际上是修改了代码块中的 执行环境 ,将obj放在了其作用域链的最后端,在 with代码块中出访非局部变量是都是先从 obj上开始查找,假如没有再依次按作用域链向上查找,因而采用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗天数的,过长的作用域链会导致查找性能下降。

  因而,除非你能肯定在 with代码中只出访 obj中的属性,否则慎用 with,替代的能采用局部变量内存须要出访的属性。

(3). 避免采用 eval和 Function

每次 eval 或 Function 构造函数作用于字符串表示的源代码时,脚本引擎都须要将源代码转换成可执行代码。这是很消耗天然资源的操作 —— 通常比单纯的函数调用慢 100倍以上。

eval 函数效率特别低,虽然事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法强化上下文,因而只能有应用程序在运行时解释代码。这对性能影响很大。

  Function 构造函数比 eval略好,因为采用此代码不会影响周围代码 ;但其速度仍很慢。

  此外,采用 eval和 Function也不利于Javascript 填充工具执行填充。

(4). 增加作用域链查找(这方面设计到一些内容的相关问题)

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

  低效率的写法:

// 全局变量 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 中区 globalVar = localVar; }

此外,要增加作用域链查找还应该增加闭包的采用。

  (5). 统计数据出访

Javascript中的统计数据出访包括间接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对间接量和局部变量的出访是最快的,对对象属性以及数组的出访须要更大的开销。当出现以下情况时,建议将统计数据放入局部变量:

  a. 对任何对象属性的出访超过 1次

  b. 对任何数组成员的出访次数超过 1次

  另外,还应当尽量的增加对对象以及数组深度查找。

(6). 字符串拼接

在 Javascript中采用”+” 号来拼接字符串效率是比较低的,因为每次运行都会开辟新的内存并生成新的字符串变量,然后将拼接结果赋值给新变量。与之相比更为高效的做法是采用数组的 join方法,即将须要拼接的字符串放在数组中最后调用其 join方法得到结果。不过虽然采用数组也有一定的开销,因而当须要拼接的字符串较多的时候能考虑用此方法。

  有关 Javascript强化的更详细介绍请参照:

Write Efficient Javascript(PPT)

Efficient JavaScript

  2. CSS选择符

  在大多数人的观念中,都觉得应用程序对 CSS选择符的解析式从左往右进行的,例如

#toc A { color: #444; }

这种两个选择符,假如是从右往左解析则效率会很高,因为第两个 ID选择大体上就把查找的范围限定了,但实际上应用程序对选择符的解析是从右往左进行的。如上面的选择符,浏览器必须遍历查找每两个 A标签的祖先节点,效率并不像之前想象的那样高。根据应用程序的这一行为特点,在写选择符的时候须要注意很多事项,有人已经一一列举了。

  3. HTML

对 HTML本身的强化现如今也越来越

  4. Image填充

图片填充是个技术活,不过现如今这方面的工具也非常多,填充之后往往能带来不错的效果,具体内容的填充原理以及方法在《 Even Faster Web Sites》第10 章有很详细的介绍,有兴趣的能去看看。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务