前端性能优化

参考资料:

https://www.cnblogs.com/coober/p/8078847.html

https://www.cnblogs.com/imyalost/p/6843622.html 

https://www.jianshu.com/p/2e69e9891c67 

https://zhuanlan.zhihu.com/p/613972631 

https://blog.csdn.net/mahoking/article/details/51472697 

web前端指网站业务逻辑之前的部分,包括浏览器加载、网站视图模型、CDN服务、HTML、 CSS、 Javascript、Image 、Flash等等各种各样的资源。

前端优化的目的有:
1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。
2. 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。

前端主要优化手段有页面级浏览器访问优化、代码级优化、反向代理、CDN优化等。

浏览器访问优化

浏览器访问从输入 URL 到页面加载完成,需要经历DNS 解析、TCP 连接、HTTP 请求抛出、服务端处理请求,HTTP 响应返回、浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户。

故浏览器加载要优化提升前端性能,有以下两大方法:

1. 减少页面加载所需时间(可以从请求数量、请求并发度及网络传输时间等方面着手);
2. 提升用户角度的观感体验(让用户觉得页面更快,则主要从让页面尽快展示入手);

减少网络时间

一.使用DNS缓存技术

使用DNS缓存技术可以让用户获得更快的DNS解析时间,一般而言,由于浏览器本身就具有一定的DNS缓存机制,所以服务端的DNS缓存并不能带来太大的性能提升。

二.减少需要传输的文件大小

在网络带宽有限的情况下,减少传输的文件大小可以提升很大的性能。常见的有将文件进行压缩的方法,除此之外,还有使用混淆等方法尽量减少JS文件和样式表的大小,从JS文件和样式表中去除不需要使用的部分等,都可以起到减少需要传输文件尺寸的作用。

三.加快文件传输速度

Internet网站的用户通常分布在一个较广阔的区域内,Internet本身的多层次网络结构导致从某一个节点到另一些节点之间的可用带宽和网络传输速度都比较慢;这种情况下使用CDN技术,让用户尽可能访问到对用户节点而言更快速的服务器就可以加快文件传输速度。

四.减少发送的请求数量、减少不必要的HTTP跳转、避免重复的资源请求

在短连接情况下,每个请求都需要经过“建立连接——发送数据——断开连接”的过程,因此减少请求数量可带来显著的性能提升;即使使用持久连接方式,由于浏览器与每个服务器之间的建立的持久连接数量是有限的,减少必须的请求也可以带来性能提升。

具体方法有:

1. 合并图片;
2. 合并压缩css样式表和js脚本;
3.去掉不必要的请求;
4.首屏加载;
5.充分利用缓存(所有静态资源都要放在服务器端并设置缓存,并且要尽量使用长缓存);
6.预加载(可使用Loading,资源加载完成后再显示页面,但加载时间过长,会造成负体验);
7.异步加载第三方资源(第三方资源不可控,会影响页面加载,所以要异步加载第三方资源);

五.利用浏览器缓存

为了充分利用浏览器缓存,需要在服务端保证每个可以被缓存的资源在被服务端返回时附带合适的expries头信息;此外,为了保证有尽可能多的内容可以被缓存,也要求网站尽可能将页面中较少改变的部分提取出来。

保证服务端返回资源的响应头带有Expires信息,使得资源可以被缓存;

用引用方式引用样式表和JS脚本。如果使用内嵌的样式表和JS脚本,每次HTML文档的变化都会导致样式表和JS脚本重新加载,无法充分利用缓存;当然,在没有缓存或样式表与JS脚本经常变动的情况下,引用方式使用样式表和JS脚本反而会导致更多的http请求;

六.资源合并与压缩

使用合并的图片文件。当页面包含很多个小图片文件时,可以考虑将小图片文件合并为一个大的图片文件,在页面使用CSS Sprites技术将大图片显示为分隔开的小图片,在没有缓存的情况下,将许多小图片合并为大图片文件可以大量减少http请求数。

使用gzip压缩。前端生产环境中将js、css、图片等文件进行压缩,通过减少数据传输量减小传输时间,节省服务器网络带宽,提高前端性能。

//npm i -D compression-webpack-plugin
configureWebpack: config => {
  const CompressionPlugin = require('compression-webpack-plugin')
  config.plugins.push(new CompressionPlugin())
}

七.提高浏览器下载的并发度

JS文件放在HTML文档最后。在某些浏览器上,JS文件的下载和执行会阻止其他页面资源文件的下载和执行,当JS文件下载和执行完,其他资源文件才可以开始下载和执行,因此,将JS文件放在HTML文档最后可以保证JS文件不会阻止任何其他元素的下载。

使用多个域名。浏览器对服务器的连接限制是基于域名的。比如S服务器有2个域名a.com和b.com,在浏览器限制最多与同一个域名建立2个连接时,浏览器实际上可以与服务器S建立4个连接;一般大型网站都拥有几个域名,根据文件类型(静态资源、动态资源、JS脚本等)选择合适的服务器进行部署,也是个很好的做法。

让页面尽早开始显示

将样式表的引用放在HTML文档的开头(如放在<Head>标签中),这样可以使样式表在一开始就被下载下来,一旦样式表下载完成,浏览器就可以使用样式表中定义的样式开始在屏幕上显示页面元素;另外,也避免了新样式表可能带来的屏幕显示的重绘。

将JS的引用放在HTML文档的最后,这样JS文件的下载和执行会在所有页面都下载完成后,不会阻止其他页面元素的显示。从用户感官上说,JS文件的下载和执行时间完全不会被用户感觉到。

代码级优化

1.设置Viewport

HTML的viewport可加快页面的渲染。

2.减少DOM结点

DOM结点太多会影响页面的渲染。

3.减少DOM操作

例如增加、修改、删除 DOM元素或者对 DOM集合进行操作。

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

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

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

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

5.避免使用 eval和 Function

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

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

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

此外,使用 eval和 Function也不利于Javascript 压缩工具执行压缩。

6.减少作用域链查找

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

// 低效率的写法:
// 全局变量 
let globalVar = 1; 
function myCallback(info){ 
    for(let i = 100000; i--;){ 
        //每次访问 globalVar 都需要查找到作用域链最顶端,本例中需要访问 100000 次 
        globalVar += i; 
    }
} 


//更高效的写法:
// 全局变量 
let globalVar = 1; 
function myCallback(info){ 
    //局部变量缓存全局变量 
    let localVar = globalVar; 
    for(let i = 100000; i--;){ 
      //访问局部变量是最快的 
      localVar += i; 
    } 
    //本例中只需要访问 2次全局变量
    在函数中只需要将 globalVar中内容的值赋给localVar 中
    globalVar = localVar; 
}

7.字符串拼接

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

8.尽量使用css3动画

合理使用requestAnimationFrame动画代替setTimeout。

9.优化高频事件

scroll、touchmove等事件尽量使用函数防抖节流等进行限制。

10.不滥用WEB字体

WEB字体需要下载、解析、重绘当前页面,尽量减少使用。

11.文件命名规则须统一且要有意义,同类型文件归类到相同的文件夹中

12.避免img、iframe等标签的src属性为空

空src会重新加载当前页面,影响速度和效率。

13.图像尽量避免使用DataURL

DataURL图像没有使用图像压缩算法,文件会变大,并且要解码后再渲染,加载慢耗时长。

14.尽可能的使用PNG格式的图片

它相对来说体积较小,可使用工具压缩,在上线前最好进行一定的优化。

15.同时在代码中进行图片的赖加载

16.减少不必要的Cookie

Cookie存储在客户端,伴随着HTTP请求在浏览器和服务器之间传递,由于cookie在访问对应域名下的资源时都会通过HTTP请求发送到服务器,从而会影响加载速度,所以尽量减少不必要的Cookie。

17.复杂动画效果,使用绝对定位让其脱离文档流

避免循环DOM元素,用transform:translate 代替 position left、right...以此来尽量减少回流和重绘。

18.尽量使用事件委托

不给每个子节点单独设置事件监听器,而是设置在其父节点上,然后利用冒泡原理设置每个子节点,避免批量绑定事件以此来减少内存消耗和DOM操作。

19.尽量使用id选择器

id选择器选择元素是最快的,具有唯一性,灵活性和优先性的优点。

20.数据访问

Javascript中的数据访问包括直接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量: 
a. 对任何对象属性的访问超过 1次 
b. 对任何数组成员的访问次数超过 1次 

另外,还应当尽可能的减少对对象以及数组深度查找。

反向代理

传统代理服务器位于浏览器一侧,代理浏览器将http请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站web服务器接收http请求。

缓存在反向代理服务器上加速用户访问速度,当这些动态内容有变化时,通过内部通知机制通知反向代理缓存失效,反向代理会重新加载最新的动态内容再次缓存起来。

此外,反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。

CDN优化

CDN(contentdistribute network,内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据。它能够实时地根据网络流量和各个节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上,其目的是使用户可以就近的取得所需内容,解决网络拥挤的状况,提高网站的响应速度。

CDN缓存的一般是静态资源,如图片、文件、CSS、script脚本、静态网页等,但是这些文件访问频度很高,将其缓存在CDN可极大改善网页的打开速度。

如果安全性对你的网站很重要,就不要使用公共的CDN,因为当你远程从CDN请求文件时,你的访问来源信息也被发送过去,一些远程的js文件可能被修改用来搜集你的用户或者系统信息,而当你使用https协议时,能选择的CDN就更加有限。

  • 37
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值