前端性能优化是一个很宽泛的概念,有不少教程都有前端性能优化的方法,这也是咱们一直在关注的一件重要事情。配合各类方式、手段、辅助系统,前端优化的最终目的都是提高用户体验,改善页面性能,咱们经常不遗余力进行前端页面优化,但却忽略了这样作的效果和意义。先不急于探究前端优化具体能够怎样去作,先看看什么是前端性能,应该怎样去了解和评价前端页面的性能。前端
一般前端性能能够认为是用户获取所须要页面数据或执行某个页面动做的一个实时性指标,通常以用户但愿获取数据的操做到用户实际得到数据的时间间隔来衡量。例如用户但愿获取数据的操做是打开某个页面,那么这个操做的前端性能就能够用该用户操做开始到屏幕展现页面内容给用户的这段时间间隔来评判。用户的等待延时能够分红两部分:可控 等待延时和 不可控 等待延时。可控 等待延时能够理解为能经过技术手段和优化来改进缩短期的部分,例如减少图片大小让请求加载更快、减小 HTTP 请求数等。不可控 等待延时则是不能或很难经过先后端技术手段来改进优化的,例如鼠标点击延时、CPU 计算时间延时、ISP(Internet Service Provider,互联网服务提供商) 网络传输延时等。因此要知道的是,前端中的全部优化都是针对 可控等待延时 这部分来进行的,下面来了解一下如何获取和评价一个页面的具体性能。后端
获取和衡量一个页面的性能,主要能够经过如下几个方面:Performance Timing API
、Prpfile
工具、页面埋点计时、资源加载时序图分析。数组
Performance Timing API 是一个支持 Internet Explorer 9
以上版本及 WebKit
内核浏览器中用于记录页面加载和解析过程当中关键时间点的机制,它能够详细记录每一个页面资源从开始加载到解析完成这一过程当中具体操做发生的时间点,这样根据开始和结束时间戳就能够计算出这个过程所花的时间了。浏览器
图 1-1为 W3C标准中 Performance Timing
资源加载和解析过程记录各个关键点的示意图,浏览器中加载和解析一个 HTML 文件的详细过程前后经历 unload、redirect、App Cache、DNS、TCP、Request、Response、Processing、onload 几个阶段,每一个过程当中开始和结束的关键时间戳浏览器已经使用 performance.timing
来记录了,因此根据这个记录并结合简单的计算,咱们就能够获得页面中每一个过程所消耗的时间。性能优化
function performanceTest(){
let timing = performance.timing,
readyStart = timing.fetchStart - timing.navigationStart,
redirectTime = timing.redirectEnd - timing.redirectStart,
appcacheTime = timing.domainLookupStart - timing.fetchStart,
unloadEventTime = timing.unloadEventEnd - timing.unloadEventStart,
lookupDomainTime = timing.domainLookupEnd - timing.domainLookupStart,
connectTime = timing.connectEnd - timing.connectStart,
requestTime = timing.responseEnd - timing.requestStart,
initDomTreeTime = timing.domInteractive - timing.responseEnd,
domReadyTime = timing.domComplete - timing.domInteractive,
loadEventTime = timing.loadEventEnd - timing.loadEventStart,
loadTime = timing.loadEventEnd - timing.navigationStart;
console.log('准备新页面时间耗时:'+readyStart);
console.log('redirect 重定向耗时:'+redirectTime);
console.log('Appcache 耗时'+appcacheTime);
console.log('unload 前文档耗时:'+unloadEventTime);
console.log('DNS 查询耗时:'+lookupDomainTime);
console.log('TCP 链接耗时:'+connectTime);
console.log('request 请求耗时:'+requestTime);
console.log('请求完毕至DOM加载:'+initDomTreeTime);
console.log('解析DOM树耗时:'+domReadyTime);
console.log('Load事件耗时:'+loadEventTime);
console.log('加载时间耗时:'+loadTime);
}
复制代码
经过上面的时间戳计算能够获得几个关键步骤所消耗的时间,对前端有意义的几个过程主要是解析 DOM 树耗时、load 事件耗时和整个加载过程耗时等,不过在页面性能获取时咱们能够尽可能获取更详细的数据信息,以供后面分析。除了资源加载解析的关键点计时,preformance 还提供了一些其余方面的功能,咱们能够根据具体须要进行选择使用。bash
performance.memory //内存占用的具体数据
performance.now() //performance.now()方法返回当前网页自performance.timing到如今的时间,能够精确到微秒,用于更加精确的计数。但实际上,目前网页性能经过毫秒来计算就足够了
performance.getEntries() //获取页面全部加载资源的performance timing 状况。浏览器获取网页时,会对网页中每个对象(脚本文件、样式表、图片文件等)发出一个HTTP请求。performance.getEntries 方法以数组形式返回全部请求的时间统计信息
performance.navigation //performance 还能够提供用户行为信息,例如网络请求的类型和重定向次数等,通常都存放在performance.navigation对象里面
performance.navigation.redirectCount //记录当前网页重定向跳转的次数
复制代码
Performance Timing API 描述了页面资源从加载到解析各个阶段的执行关键点时间记录,可是没法统计 JavaScript 执行过程当中系统资源的占用状况。Profile 是 Chrome 和 Firefox 等标准浏览器提供的一种用于测试页面脚本运行时系统内存和 CPU 资源占用状况的 API,以 Chrome 浏览器为例,结合 Profile,能够实现如下几个功能。网络
1.分析页面脚本执行过程当中最耗资源的操做app
2.记录页面脚本执行过程当中 JavaScript 对象消耗的内存与堆栈的使用状况dom
3.检测页面脚本执行过程当中 CPU 占用状况前端优化
使用 console.profile()
和console.profileEnd()
就能够分析中间一段代码执行时系统的内存或 CPU 资源的消耗状况,而后配合浏览器的 Profile 查看比较消耗系统内存或 CPU 资源的操做,这样就能够有针对性的进行优化了。
console.profile();
//TODOS,须要测试的页面逻辑动做
for(let i = 0; i < 100000; i ++){
console.log(i * i);
}
console.profileEnd();
复制代码
使用Profile能够在必定程度上帮助咱们分析页面的性能,但缺点是不够灵活。实际项目中,咱们不会多关注页面的内存或CPU资源的消耗状况,由于JavaScript有自动内存回收机制。咱们关注更多的是页面脚本逻辑执行的时间。除了Performance Timing 的关键过程耗时计算,咱们还但愿检测代码的具体解析或执行时间,这就不能写不少的console.profile()
和console.profileEnd()
来逐段实现,为了更加简单地处理这种状况,每每选择经过脚本埋点计时的方式来统计没部分代码的运行时间。
页面 JavaScript 埋点计时比较容易实现,和 Performance Timing 记录时间戳有点相似,咱们能够记录 JavaScript 代码开始执行的时间戳,后面在须要记录的地方埋点记录结束时的时间戳,最后经过差值来计算一段 HTML 解析或 JavaScript 解析执行的时间。为了方便操做,能够将某个操做开始和结束的时间戳记录到一个数组中,而后分析数组之间的间隔就获得每一个步骤的执行时间,下面来看一个时间点记录和分析的例子。
let timeList = [];
function addTime(tag) {timeList.push({"tag":tag,"time":+new Date()});}
addTime("loading");
timeList.push({"tag":"load","time":+new Date()});
//TODOS,load加载时的操做
timeList.push({"tag":"load","time":+new Date()});
timeList.push({"tag":"process","time":+new Date()});
//TODOS,process处理时的操做
timeList.push({"tag":"process","time":+new Date()});
console.log(parseTime(timeList)); //输出{load:时间毫秒数,process: 时间毫秒数}
function parseTime(time) {
let timeStep={},
endTime;
for(let i = 0,len = time.length; i < len; i ++){
if(!time[i]) continue;
endTime = {};
for(let j = i+1; j < len; j++){
if(time[j] && time[i].tag == time[j].tag){
endTime.tag = time[j].tag;
endTime.time = time[j].time;
time[j] = null;
}
}
if(endTime.time >= 0 && endTime.tag){
timeStep[endTime.tag] = endTime.time - time[i].time;
}
}
return timeStep;
}
复制代码
这种方式经常在移动端页面中使用,由于移动端浏览器 HTML 解析和 JavaScript 执行相对较慢,一般为了性能优化,咱们须要找到页面中执行 JavaScript 耗时的操做,若是将关键 JavaScript 的执行过程进行埋点计时并上报,就能够轻松找出 JavaScript 执行慢的地方,并有针对性地进行优化。
咱们还能够借助浏览器或其余工具的资源加载时序图来帮助分析页面资源加载过程当中的性能问题。这种方法能够粗粒度地宏观分析浏览器的全部资源文件请求耗时和文件加载顺序状况,如保证 CSS 和数据请求等关键资源优先加载,JavaScript 文件和页面中非关键性图片等内容延后加载。若是由于某个资源的加载十分耗时而阻塞了页面的内容展现,那就要着重考虑。因此,咱们须要经过资源加载时序图来辅助分析页面上资源加载顺序的问题。
图 1-2 为使用 Fiddler 抓取浏览器访问地址时的资源加载时序图,图 1-3 为 Chrome 浏览器访问猫眼电影官网时的资源加载时序图.根据资源加载时序图咱们能够很直观地看到页面上各个资源加载过程所须要的时间和前后顺序,有利于找出加载过程当中比较耗时的文件资源,帮助咱们有针对性地进行优化。
经过上文介绍的利用
Performance Timing API
、Prpfile
工具、页面埋点计时、资源加载时序图分析几个方面来获取和衡量一个页面的性能,找出加载过程当中比较耗时的文件资源,帮助咱们有针对性地进行优化。医病必须诊断找到病因,前端性能测试在前端性能优化中属于诊断工做,只有找到病因,才能进行针对性治疗优化。在此欢迎你们加入QQ前端技术交流群544587175
,在后续我会从桌面浏览器和移动端浏览器两个方面详细讲解不一样终端的优化策略,敬请关注......