前端性能优化(十二)

优化JavaScript的执行效率

页面里的动画效果大多是通过JavaScript触发的。有些是直接修改DOM元素样式属性而产生的,有些则是由数据计算而产生的,比如搜索或排序。错误的执行时机和太长的时间消耗,是常见的导致JavaScript性能低下的原因。你需要尽量减少这两方面对你的JavaScript代码带来的执行性能的影响。

JavaScript性能分析是一门艺术活,因为你所写的JavaScript代码跟实际执行的代码完全是两回事。现代浏览器都会使用JIT编译器和其他优化手段来使你的JavaScript代码能尽可能执行得更快,这个编译和优化的过程会对代码产生极大的改动。

Note

  • 如果你想看看JIT到底长什么样,请参考:IRHydra2 by Vyacheslav Egorov。这篇文章讲解了页面中的JavaScript代码在Chrome的V8引擎中被优化时的中间状态。

尽管如此,在优化JavaScript程序的执行速度方面,还是有一些你力所能及的事。

使用requestAnimationFrame

假设页面上有一个动画效果,你想在动画刚刚发生的那一刻的时候做点什么,比如运行一段JavaScript程序。那么唯一能保证这个运行时机的,就是requestAnimationFrame

/**
 * If run as a requestAnimationFrame callback, this
 * will be run at the start of the frame.
 */
function updateScreen(time) {
  // Make visual updates here.
}

requestAnimationFrame(updateScreen);

很多框架和示例代码都是用setTimeoutsetInterval来实现页面中的动画效果。这种实现方式的问题是,你在setTimeoutsetInterval中指定的回调函数的执行时机是无法保证的。它将在这一帧动画的_某个时间点_被执行,很可能是在帧结束的时候。这就意味这我们可能失去这一帧的信息,也就是发生jank。

事实上,jQuery中animate函数就是用setTimeout来实现的动画的!我建议你去给它打个补丁,用requestAnimationFrame来取代setTimeout

降低代码复杂度或者使用Web Workers

JavaScript代码是运行在浏览器的主线程上的。与此同时,浏览器的主线程还负责样式计算、布局,甚至绘制(多数情况下)的工作。可以想象,如果JavaScript代码运行时间过长,就会阻塞主线程上其他的渲染工作,很可能就会导致帧丢失。

因此,你需要认真规划一下你的JavaScript程序的运行时机和运行耗时。比如,如果你要在一个动画(比如页面滚动)执行过程中运行JavaScript程序,那么理想情况是把这段JavaScript程序的运行耗时控制在3-4毫秒以内。如果长于这个时间,那么就有帧丢失的风险。另一方面,在浏览器空闲的时候,你可以有更多时间来运行JavaScript程序。

大多数情况下,你可以把纯计算工作放到Web Workers中做(如果这些计算工作不会涉及DOM元素的存取)。一般来说,JavaScript中的数据处理工作,比如排序或搜索,一般都适合这种处理方式。

var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);

// The main thread is now free to continue working on other things...

dataSortWorker.addEventListener(‘message‘, function(evt) {
   var sortedData = e.data;
   // Update data on screen...
});

正如前面提到的,并不是所有的JavaScript代码都适合这种方式,因为Web Workers无法访问DOM元素。如果你的JavaScript代码需要存取DOM元素,也就是说必须在主线程上运行,那么可以考虑批处理的方式:把任务细分为若干个小任务,每个小任务耗时很少,各自放在一个requestAnimationFrame中回调运行。

var taskList = breakBigTaskIntoMicroTasks(monsterTaskList);
requestAnimationFrame(processTaskList);

function processTaskList(taskStartTime) {
  var taskFinishTime;

  do {
    // Assume the next task is pushed onto a stack.
    var nextTask = taskList.pop();

    // Process nextTask.
    processTask(nextTask);

    // Go again if there’s enough time to do the next task.
    taskFinishTime = window.performance.now();
  } while (taskFinishTime - taskStartTime < 3);

  if (taskList.length > 0)
    requestAnimationFrame(processTaskList);

}

如果采用划分小任务的方式,那么你需要确保给用户呈现一个好的UX/UI,使得用户能感知到当前浏览器正在处理一个任务,比如使用一个进度条或者指示器。不管怎样,这种方式能使释放浏览器的主线程,使你的web应用总能对用户交互保持响应。

了解JavaScript的“帧税”

当我们评价一个框架、库或者自己写的JavaScript代码时,很重要的一点就是要分析每一帧中JavaScript代码运行的消耗。对性能很敏感的动画效果(比如渐变或滚动)来说,这一点尤其重要。

对于JavaScript代码的性能分析,最好的方式就是使用Chrom的DevTools。一般来说,通过它你能获取到这些细节:

如果你发现了运行时间很长的JavaScript代码,那么你可以开启DevTools中顶部的JavaScript profiler选项:

但是,这个选项本身的运行也会有一些消耗。因此,确保只有在你需要查看更多运行时细节的时候才开启它。开启这个选项之后,再执行一次页面分析动作,你会看到更多细节:

有了这些信息,你就能分析出JavaScript代码对于页面渲染性能的影响了,从而发现并修复JavaScript代码中性能低下的部分。至于如何修复,就像前面说的,你可以删除它或者把它放到Web Worker中去,以释放主线程来响应其他任务。

避免对JavaScript代码进行微优化

对于一个任务,如果换一种实现方式,浏览器的执行速度可以快100倍的话,是非常酷的。比如,读取一个元素的offsetTop属性就比计算它的getBoundingClientRect()要快。但一般情况下,在每一帧中运行的JavaScript代码之中调用这些函数的次数都是有限的。因此,在这些微优化上花再大的精力,整体上JavaScript代码的性能可能也就获得若干毫秒的提升。这是不划算的。

但是,如果你是做一个游戏,或者计算密集型的web应用,那么这条建议可能不适合你。因为你很可能要在一帧中执行很多计算工作,这种情况下需要争取做一切可能的性能优化。

简而言之:慎用微优化。因为一般来说它对你的web应用效果不大。

时间: 2024-10-01 17:23:03

前端性能优化(十二)的相关文章

前端性能优化(二)

规则5:压缩组件 ? 压缩组件可以使响应包变小,缩短传输时间.HTTP1.1中,可以通过Accept-Encoding:gzip(gzip是目前最理想的压缩方法)进行控制(上述已提及).需要注意的是:图片和pdf不应该压缩,因为它们本来就已经被压缩过了,试图对它们压缩只会浪费CPU资源,还可能增加文件大小. 代理缓存 ? 上述阐述的方式对于浏览器和服务器直接通信会工作的很好,当浏览器通过代理发送过来请求时,情况就复杂了,综述一下具体请查看:Vary.mod_gzip 网站用户少或注重带宽开销:V

WEB前端性能优化之二——css优化

1.把样式表置于顶部 现把样式表放到文档的< head />内部似乎会加快页面的下载速度.这是因为把样式表放到< head />内会使页面有步骤的加载显示.HTML规范清 楚指出样式表要放包含在页面的< head />区域内:“和< a />不同,< link />只能出现在文档的< head />区域内,尽管它可以多次使用它”.无论是引起白屏还是出现没有样式化的内容都不值得去尝试.最好的方案就是按照HTML规范在文 档< he

Oracle 学习之 性能优化(十二) 分区表

一.分区概念 Oracle允许将表.索引.索引组织表细分成更小的片,每个片我们称之为分区.分区有其自己的名字和存储参数. 如下图: 每行数据只能属于一个分区,分区键决定数据行属于哪个分区.分区键由一个或多个列组成.Oracle自动的将数据的DML操作映射到相应的分区中. 何时使用分区表: Tables greater than 2 GB should always be considered as candidates for partitioning. Tables containing hi

关于Yahoo十四条军规与前端性能优化

关于Yahoo十四条军规与前端性能优化 热度 4已有 223 次阅读2014-8-3 15:01 |个人分类:前端相关|系统分类:前端优化| 前端优化, yahoo, 性能优化 启用Gzip压缩.Gzip的思想就是把文件先在服务器端进行压缩,然后再传输.这样可以显著减少文件传输的大小.传输完毕后浏览器会 重新对压缩过的内容进行解压缩,并执行.目前的浏览器都能“良好”地支持 gzip.不仅浏览器可以识别,而且各大“爬虫”也同样可以识别,各位seoer可以放下心了.而且gzip的压缩比例非常大,一般

vue-小爱ADMIN系列文章(二):微信微博等分享,国际化,前端性能优化,nginx服务器部署

最近在做我的小爱ADMIN后台管理系统,结合当前市场后台管理系统对相关功能的需求,我又开始新增了一些新的功能和组件,如分享功能组件,项目国际化功能:项目完成后,部署在nginx服务器,发现首次访问的速度特别慢,严重的影响了用户体验,因此,我又开始进行了一系列的前端性能优化;以及将优化后的项目部署到nginx服务器二级子目录的注意细节. 效果演示地址 github地址 分享功能 背景说明 用微信,微博等做网站的第三方登录及用微信和支付宝进行支付,都需要注册开发者账号和添加网站应用,比较麻烦.另外,

web前端性能优化

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个“Duang”的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户体验,也决

Web前端性能优化——如何提高页面加载速度

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个"Duang"的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户

【转】Web前端性能优化——如何提高页面加载速度

前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个"Duang"的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页.也许这样讲,各位还不会有太多感触,接下来我列举一组数据:Google网站访问速度每慢400ms就导致用户搜索请 求下降0.59%;Amazon每增加100ms网站延迟将导致收入下降1%;雅虎如果有400ms延迟会导致流量下降5-9%.网站的加载速度严重影响了用户

CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化

目录 一.浏览器兼容 1.1.概要 1.2.浏览器内核 1.3.浏览器市场份额(Browser Market Share) 1.4.兼容的一般标准 1.5.CSS Reset 1.6.CSS Hack 1.6.1.条件注释法 1.6.2.样式内属性标记法 1.6.3.选择器前缀法 1.7.文档模式 (X-UA-Compatible) 1.8.javascript兼容 二.前端性能优化 2.1.概要 2.2.减少HTTP请求数量 2.2.1.图片地图 2.2.2.精灵图片(Sprite) 2.2.

WebPack实例与前端性能优化

[前端构建]WebPack实例与前端性能优化 计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几何时,我们是如上图的方式引入JS资源的,相信现在很少遇见了.近年来Web前端开发领域朝着规范开发的方向演进.体现在以下两点: MVC研发构架.多多益处(逻辑清晰,程序注重数据与表现分离,可读性强,利于规避和排查问题...) 构建工具层出不穷.多多益处(提