前端性能常见优化点分析

前言

网站的划分一般为二:前端和后台。我们可以理解成后台是用来实现网站的功能的,比如:实现用户注册,用户能够为文章发表评论等等。而前端呢?其实应该是属于功能的表现。并且影响用户访问体验的绝大部分来自前端页面。

而我们建设网站的目的是什么呢?不就是为了让目标人群来访问吗?所以我们可以理解成前端才是真正和用户接触的。除了后台需要在性能上做优化外,其实前端的页面更需要在性能优化上下功夫,只有这样才能给我们的用户带来更好的用户体验。就好像,好多人问,男人在找女朋友的时候是不是只看外表,一些智慧的男人给出了这样的回答:脸蛋和身材决定了我是否想去了解她的思想,思想决定了我是否会一票否决她的脸蛋和身材。同理,网站也是这样,网站前端的用户体验决定了用户是否想要去使用网站的功能,而网站的功能决定了用户是否会一票否决前端体验。

不仅仅如此,如果前端优化得好,他不仅可以为企业节约成本,他还能给用户带来更多的用户,因为增强的用户体验。说了这么多,那么我们应该如何对我们前端的页面进行性能优化呢?

一般说来,web前端指网站业务逻辑之前的部分,包括浏览器加载、网站视图模型、图片服务、CDN服务等,主要优化手段有浏览器访问、CDN、服务端渲染以及http相关等等。

但是做性能优化有一点是很重要的,就是各个方法之间的balance,我们不能以为我们使用了某个方法,网页体验就能更好,加载速度就能更快,所有的性能改进方法都要以实际体验为准。

1、请减少HTTP请求以及dns优化:

在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出。

一个正常HTTP请求的流程简述:如在浏览器中输入"www.xxxxxx.com"并按下回车,浏览器再与这个URL指向的服务器建立连接,然后浏览器才能向服务器发送请求信息,服务器在接受到请求的信息后再返回相应的信息,浏览器接收到来自服务器的应答信息后,对这些数据解释执行。

而当我们请求的网页文件中有很多图片、CSS、JS甚至音乐等信息时,将会频繁的与服务器建立连接,与释放连接,这必定会造成资源的浪费,且每个HTTP请求都会对服务器和浏览器产生性能负担。

网速相同的条件下,下载一个100KB的图片比下载两个50KB的图片要耗费的网络资源更多。所以,请减少HTTP请求。

解决办法:

  1. 资源的合并与压缩

合并CSS和JS文件,css压缩以及js压缩,在当前的前端生态中,我们可以结合webpack等工具自动帮我们做压缩,比如uglyfy-js等工具,甚至是利用tree shaking等功能去自动帮我们精简代码,但是请注意,不能过度合并资源,否则会造成首页加载过慢的问题。

  1. 图片处理
    1. 选择合适的图片类型,如对色彩要求不严格,我们可以考虑使用jpg,不用支持透明我们可以考虑使用png24,支持webp格式优先考虑使用webp格式(android上对webp支持较好,ios支持较差,现在淘宝是采用这种模式,)
    1. 小图片采用base64的格式,直接嵌入代码中,可以帮我们减少http请求,但是同样,这个会造成我们代码的提及变大,请求的速度会减慢,这个就是上面所说的需要一个balance,现在精灵图的方式已经不是特别流行了,目前大互联网站只发现Facebook在使用
    1. 使用图片预加载和图片懒加载,对于类似瀑布流布局或电商等图片较多的网站,合理使用图片预加载的方式可以使首页可以更加快速打开,并且减少带宽消耗
    1. 对于 小icon,我们可以考虑使用字体图标,它比图片更轻量级并且更好控制
2、请正确理解 Repaint 和 Reflow已经图层等概念
  • Repaint(重绘)就是在一个元素的外观被改变,但没有改变布局(宽高)的情况下发生,如改变visibility、outline、背景色等等。

  • Reflow(回流)就是DOM的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证DOM树上的所有其它结点的visibility属性,这也是Reflow低效的原因。如:改变窗囗大小、改变文字大小、内容的改变、浏览器窗口变化,style属性的改变等等。如果Reflow的过于频繁,CPU使用率就会噌噌的往上涨,所以前端也就有必要知道 Repaint 和 Reflow的知识。

回流一定会重绘,但是重绘不一定会造成回流,所以如果可以实现相同效果,采用重绘的方式可以帮我节省回流的时间

比如上面提到通过设置style属性改变结点样式的话,每设置一次都会导致一次reflow,所以最好通过设置class的方式; 有动画效果的元素,它的position属性应当设为fixed或absolute,这样不会影响其它元素的布局;如果功能需求上不能设置position为fixed或absolute,那么就权衡速度的平滑性。还有比如动画使用translate的方式而不是用定位的方式,透明度使用rgba而不用使用opacity等,有些不经意的操作也会导致大量回流,如在循环中使用offsetWidth等。

图层: 浏览器会为经常变化的部分形成一个图层,比如video等,我们可以通过chrome的layout工具找到图层,形成一个新图层可以让浏览器只回流变化的部分,比如使用will-change可以将一个元素新建一个图层,对于gif等变化较多的我们可以考虑使用新建图层的方式,但是注意图层过多也会导致图层合成的时候花费大量时间。

3、请减少对DOM的操作

基本原理:对DOM操作的代价是高昂的,这在网页应用中的通常是一个性能瓶颈。

天生就慢。在《高性能JavaScript》中这么比喻:“把DOM看成一个岛屿,把JavaScript(ECMAScript)看成另一个岛屿,两者之间以一座收费桥连接”。所以每次访问DOM都会教一个过桥费,而访问的次数越多,交的费用也就越多。所以一般建议尽量减少过桥次数。

解决办法:

  • 1.修改和访问DOM元素会造成页面的Repaint和Reflow,循环对DOM操作更是罪恶的行为。所以请合理的使用JavaScript变量储存内容,考虑大量DOM元素中循环的性能开销,在循环结束时一次性写入。

  • 2.减少对DOM元素的查询和修改,查询时可将其赋值给局部变量,使用innerHTML的方式一次插入。

    1. 考虑使用前端mv*框架
4. 使用CDN加速(内容分发网络)

基本原理:

CDN的全称是Content Delivery Network,即内容分发网络。

简单来说它主要的工作是把我们需要被分发的内容分发到世界各地的各个节点上,让世界各地的人都可以在距离最近的网络节点拿到想要拿到的内容,减少网络传输距离从而达到加速的目的。

当用户发起内容请求时,通过cdn厂商的智能DNS域名解析拿到cdn厂商边缘节点服务器的ip(cdn厂商会在运营商注册),然后向边缘节点服务器发起请求,请求内容数据(这件事情由浏览器完成),边缘节点会检测当前节点是否有数据,如果没有就去front(父级节点,父级可能还会有父级节点,不同的网络环境策略会略有不同)节点要,如果还找不到就去源站拿,并依次序返回。如果某个边缘节点可以找到,会先校验内容有效期,当确定有效期之后返回给用户

但是使用CDN的方式请注意浏览器有有一个同域名并发请求上限,所以如果cdn资源过多,我们可以考虑使用多个cdn域名

5.将CSS和JS放到外部文件中引用,CSS放头,JS放尾

基本原理:

引入外部文件好处是显而易见的,而且是项目稍稍复杂一点的时候就有必要了这样做了,易维护、易扩展,方便管理和重复利用。

正确的方式:

JavaScript是浏览器中的霸主,为什么这么说,因为在浏览器在执行JavaScript代码时,不能同时做其它事情,即每次出现都会让页面等待脚本的解析和执行(不论JavaScript是内嵌的还是外链的),JavaScript代码执行完成后,才继续渲染页面。这个也就是JavaScript的阻塞特性。因为这个阻塞的特点,建议把JavaScript代码放到标签以前,这样既能有效的防止JavaScript的阻塞,又能使得页面的HTML结构能更快的释放。

HTML规范清楚指出CSS要放包含在页面的区域内,这里就不多解释了。

但是有点需要注意,浏览器js会阻止html的渲染,但是我们为什么可以加载js下面的资源呢?其实浏览器内部也是有一个资源请求的预检机制的,可以在js执行时并发的请求资源

5、在前端框架中使用异步加载以及服务端渲染
  1. 为什么需要异步加载

现在流行的使用webpack的工具构建的前端工程,可以合并我们的js和css以及image等资源,合并为一个文件,那么是不是我们减少了http请求的数量那我们网站的性能优化就更好了呢?no,可能我们网站静态资源很多,全部揉进一个js文件,那这个文件会是非常巨大的,首页资源加载的速度会非常慢,那么有什么办法可以优化呢?答案是异步加载,我们不打包所有的组件文件,将文件拆分开来,当我们使用到这个组件的时候,我们才去加载,通常我们配合webpack以及异步加载方法import('a.js')

  1. 服务端渲染

客户端渲染和服务器端渲染的最重要的区别就是究竟是谁来完成html文件的完整拼接,如果是在服务器端完成的,然后返回给客户端,就是服务器端渲染,而如果是前端做了更多的工作完成了html的拼接,则就是客户端渲染, 例如我们在react中我们可以使用renderToString将组件渲染为html

优点:

  • 首屏加载快

相比于加载单页应用,我只需要加载当前页面的内容,而不需要像 React 或者 Vue 一样加载全部的 js 文件(当然,单页应用文件加载过大的情况可以使用 code spliting 来解决

  • SEO 优化

对于单页应用,搜索引擎并不能收录到 ajax 爬取数据之后然后再动态 js 渲染出来的页面

6. 使用缓存和客户端本地存储

对于很少变化的静态资源,我们可以考虑使用缓存,并且设置一定的过期时间,可以有效的提升页面的加载速度和带宽的节约

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值