淘宝公告栏滚动代码(淘宝滚动公告栏怎么设置)

wangge888 2 0

淘宝公告栏滚动代码(淘宝滚动公告栏怎么设置)-第1张图片-旺哥开店网

  

  

  

想必很多人都已经看到了新版的淘宝首页,它与以往不太一样,这一版页面中四处弥散着个性化的味道,由于独特的个性化需求,前端也面临各方面的技术挑战:   

数据来源多串行请求渲染一个模块运营数据和个性化数据匹配和管理数据兜底容灾   

本次淘宝首页改版,虽已不再支持IE6和IE7等低版本的古董浏览器,但依然存在多个影响首页性能的因素:   

依赖系统过多,数据的请求分为三块,其一是静态资源(如js/css/image/iconfont等);其二是推到CDN的静态数据(如运营填写的数据、前端配置信息等);其三是后端接口,不同的模块对应不同的业务,而且页面中还有不少的广告内容,粗略估计页面刚加载时首屏发出的接口请求就有8个,滚到最底下,得发出20多个请求。无法直接输出首屏数据,首屏很多数据是通过异步请求获取的,由于系统限制,这些请求不可避免,而且请求个数较多,十分影响首屏时间。模块过多,为了能够在后台隔离运营之间填写数据的权限,模块必须做细粒度的拆分,如下图所示:   

  

  

一个简单的模块必须拆分成多个行业小模块,页面中其他位置也是如此,而且这些被拆分出来的模块还不一定会展现出来,需要让算法告诉前端展示哪些模块。   

图片过多,翻页往下滚动,很明显看到,页面整屏整屏的图片,有些图片是运营填写,有些图片由个性化接口提供,这些图片都没有固定的尺寸。网页性能衡量指标   

网页性能衡量指标有很多,倘若能够把握关键的几个,集中优化,性能自然也就上去了。   

  

FPS   

  

最能反映页面性能的一个指标是FPS(framepersecond),一般系统设定屏幕的刷新率为60fps,当页面元素动画、滚动或者渐变时绘制速率小于60,就会不流畅,小于24就会卡顿,小于12基本认定卡爆了。   

  

1帧的时长约16ms,除去系统上下文切换开销,每一帧中只留给我们10ms左右的程序处理时间,如果一段脚本的处理时间超过10ms,那么这一帧就可以被认定为丢失,如果处理时间超过26ms,可以认定连续两帧丢失,依次类推。我们不能容忍页面中多次出现连续丢失五六帧的情况,也就是说必须想办法分拆执行时间超过80ms的代码程序,这个工作并不轻松。   

  

页面在刚开始载入的时候,需要初始化很多程序,也可能有大量耗时的DOM操作,所以前1s的必要操作会导致帧率很低,我们可以忽略。当然,这是对PC而言,Mobile内容少,无论是DOM还是JS脚本量都远小于PC,1s可能就有点长了。   

  

DOMContentLoaded和Load   

  

DOM加载并且解析完成才会触发DOMContentLoaded事件,倘若源码输出的内容过多,客户端解析DOM的时间也会响应加长,不要小看这里的解析时间,如果DOM数量增加2000个并且嵌套层级较深,解析时间也会相应增加50-200ms,这个消耗对大多数页面来说其实是没必要的,保证首屏输出即可,后续的内容只保留钩子,利用JS动态渲染。   

  

Load时间可以用来衡量首屏加载中,客户端接受的信息总量,如果在首屏中充满了大尺寸图片或者客户端与后端建立连接次数较多,Load时间也会相应被拖长。   

  

流畅度   

  

流畅度是对FPS的视觉反馈,FPS值越高,视觉呈现越流畅。为了保障页面的加载速度,很多内容不会在页面打开的时候全部加载到客户端。这里提到的流畅度是等待过程中的视觉缓冲,如下方是GooglePlus页面的一个效果图:   

  

  

  

墙内访问google的速度不是很快,上面元素中的的很多内容都是通过异步方式加载,而从上图可以看出Google并没有让用户产生等待的焦虑感。   

淘宝首页的性能优化   

由于平台限制,淘宝首页面临一个先天的性能缺陷,首屏的渲染需要从7个不同的后端取数据,这些数据请求是难以合并的,如果用户屏幕比较大,则首屏的面积也比较大,对应的后端平台数据接口就更多。数据是个性化内容或者为广告内容,故请求也不能缓存。   

  

关键模块优先   

  

不论用户首屏的面积有多大,保证关键模块优先加载。下面代码片段是初始化所有模块的核心部分:   

  $('.J_Module').each(function(mod){   var$mod=$(mod);   varname=$mod.attr('tms');   vardata=$mod.attr('tms-data');   if($mod.hasClass('tb-pass')){   Reporter.send({   msg:"跳过模块"+name   });   return;   }   //保证首屏模块先加载   if(/promo|tmall|tanx|notice|member/.test(name)){   window.requestNextAnimationFrame(function(){   //最后一个参数为Force,强制渲染,不懒加载处理   newLoader($mod,data,/tanx/.test(name));   });   }else{   //剩下的模块进入懒加载队列   lazyQueue.push({   $mod:$mod,   data:data,   force:/fixedtool|decorations|bubble/.test(name)   });   }   });   

TMS输出的模块都会包含一个.J_Module钩子,并且会预先加载js和css文件。   

  

对于无JS内容的模块,会预先打上tb-pass的标记,初始化的时候跳过此模块;对于首屏模块关键模块,会直接进入懒加载监控:   

  //$box进入浏览器视窗后渲染   //newLoader($box,data)->   datalazyload.addCallback($box,function(){   self.loadModule($box,data);   });   //$box立即渲染   //newLoader($box,data,true)->   self.loadModule($box,data);   

除必须立即加载的模块外,关键模块被加到懒加载监控,原因是,部分用户进入页面就可能急速往下拖拽页面,此时,没必要渲染这些首屏模块。   

  

非关键模块统一送到lazyQueue队列,没有基于将非关键模块加入到懒加载监控,这里有两个原因:   

一旦加入监控,程序滚动就需要对每个模块做计算判断,模块太多,这里可能存在性能损失如果关键模块还没有加载好,非关键模块进入视窗就会开始渲染,这势必会影响关键模块的渲染   

那么,什么时候开始加载非关键模块呢?   

  var__lazyLoaded=false;   functionrunLazyQueue(){   if(__lazyLoaded){   return;   }   __lazyLoaded=true;   $(window).detach("mousemovescrollmousedowntouchstarttouchmovekeydownresizeonload",runLazyQueue);   varmodule;   while(module=lazyQueue.shift()){   ~function(m){   //保证在浏览器空闲时间处理JS程序,保证不阻塞   window.requestNextAnimationFrame(function(){   newLoader(m.$mod,m.data,m.force);   });   }(module);   }   }   $(window).on("mousemovescrollmousedowntouchstarttouchmovekeydownresizeonload",runLazyQueue);   //担心未触发onload事件,5s之后执行懒加载队列   window.requestNextAnimationFrame(function(){   runLazyQueue();   },5E3);   

上面的代码应该十分清晰,两种请求下会开始将非关键模块加入懒加载监控:   

当页面中触发mousemovescrollmousedowntouchstarttouchmovekeydownresizeonload这些事件的时候,说明用户开始与页面交互了,程序必须开始加载。如果用户没有交互,但是页面已经onload了,程序当然不能浪费这个绝佳的空档机会,趁机加载内容;经测试,部分情况下,onload事件没有触发(原因尚不知),所以还设定了一个超时加载,5s之后,不论页面加载情况如何,都会将剩下的非关键模块加入到懒加载监控。   

懒执行,有交互才执行   

  

如果说上面的优化叫做懒加载,那么这里的优化可以称之为懒执行。   

  

首页上有几个模块是包含交互的,如头条区域的tab,便民服务的浮层和主题市场的浮层,部分用户进入页面可能根本不会使用这些功能,所以程序上并没有对这些模块做彻底的初始化,而是等到用户hover到这个模块上再执行全部逻辑。   

  

更懒的执行,刷新页面才执行   

  

首屏中有两个次要请求,一个是主题市场的hot标,将用户最常逛的三个类目打标;第二个是个人中心的背景,不同的城市会展示不同的背景图片,这里需要请求拿到城市信息。   

  

这两处的渲染策略都是,在程序的idle(空闲)时期,或者window.onload十秒之后去请求,然后将请求的结果缓存到本地,当用户第二次访问淘宝首页时能够看到效果。这是一种更懒的执行,用户刷新页面才看得到.这种优化是产品能够接受,也是技术上合理的优化手段。   

  

图片尺寸的控制和懒加载   

  

不论图片链接的来源是运营填写还是接口输出,都难以保证图片具备恰当的宽高,加上如今retina的屏幕越来越多,对于这种用户也要提供优质的视觉体验,图片这块的处理并不轻松。   

     

阿里CDN是支持对图片尺寸做压缩处理的,如下图为200x200尺寸的图片:   

  

  

  

加上_100x100.jpg的参数后,会变成小尺寸:   

  

  

  

我们知道webp格式的图片比对应的jpg要小三分之一,如上图加上_.webp参数后:   

  

  

  

视觉效果并没有什么折扣,但是图片体积缩小了三分之一,图片越大,节省的越明显。显然,淘宝首页的所有图片都做了如上的限制,针对坑位大小对图片做压缩处理,只是这里需要注意的是,运营填写的图片可能已经是压缩过的,如:   

  $img='//g.alicdn.com/real/path/to/img.png_400x400.jpg';      

上面这种情况,图片是不会正确展示的。首页对所有的图片的懒加载都做了统一的函数处理:   

  src=src.replace(/\s/g,'');   vararr;   if(/(_\d{2,}x\d{2,}\w*?\.(?:jpg|png)){2,}/.test(src)&&src.indexOf('_!!')==-1){   arr=src.split('_');   if(arr[arr.length-1]=='.webp'){   src=[arr[0],arr[arr.length-2],arr[arr.length-1]].join('_');   }else{   src=[arr[0],arr[arr.length-1]].join('_');   }   }   if(src.indexOf('_!!')>-1){   src=src.replace(/((_\d{2,}x\d{2,}[\w\d]*?|_co0)\.(jpg|png))+/,'$1');   }   WebP.isSupport(function(isSupportWebp){   //https协议访问存在问题IE8,去schema   if(/^http:/.test(src)){   src=src.slice(5);   }   //支持webp格式,并且host以taobaocdn和alicdn结尾,并且不是s.gif图片   if(isSupportWebp&&/(taobaocdn|alicdn)\.com/.test(src)&&(src.indexOf('.jpg')||   src.indexOf('.png'))&&!/webp/.test(src)&&!ignoreWebP&&!/\/s\.gif$/.test(src)){   src+='_.webp';   }   $img.attr('src',src);   });   

模块去钩子,走配置   

  

TMS的模块在输出的时候会将数据的id放在钩子上:   

  
  

如果模块是异步展示的,可以通过tms-datakey找到模块数据,而首页的个性化是从几十上百个模块中通过算法选出几个,如果把这些模块钩子全部输出来,虽说取数据方便了很多,却存在大量的冗余,对此的优化策略是:将数据格式相同的模块单独拿出来,新建页面作为数据页。所以可以在源码中看到好几段这样的配置信息:   

     

减少了大量的源码以及对DOM的解析。   

  

低频修改模块,缓存请求   

  

有一些模块数据是很少被修改的,比如接口的兜底数据、阿里APP模块数据等,可以通过调整参数,设置模块的缓存时间,如:   

  io({   url:URL,   dataType:'jsonp',   cache:true,   jsonpCallback:'jsonp'+Math.floor(newDate/(1000*60)),   success:function(){   //...   }   });   

Math.floor(newDate/(1000*60))这个数值在一分钟内是不会发生变化的,也就是说将这个请求在本地缓存一分钟,对于低频修改模块,缓存时间可以设置为一天,即:   

  Math.floor(newDate/(1000*60*60*24))   

当然,我们也可以采用本地储存的方式缓存这个模块数据:   

  offline.setItem('cache-moduleName',JSON.stringify(data),1000*60*60*24);   

缓存过期时间设置为1天,淘宝首页主要采用本地缓存的方式。   

  

使用缓动效果减少等待的焦急感   

  

这方面的优化不是很多,但是也有一点效果,很多模块的展示并不是干巴巴的.show(),而是通过动画效果,缓动呈现,这方面的优化推荐使用CSS3属性去控制,性能消耗会少很多。   

优化的思考角度   

页面优化的切入点很多,我们不一定能够面面俱到,但是对于一个承载较大流量的页面来说,下面几条必须有效执行:   

首屏一定要快滚屏一定要流畅能不加载的先别加载能不执行的先别执行渐进展现、圆滑展现   

当然,性能优化的切入角度不仅仅是上几个方面,对照Chrome的Timeline柱状图和折线图,我们还可以找到很多优化的点,如:   

  

  

在1.0s左右存在一次painting阻塞,可能因为一次性展示的模块面积过大从FPS的柱状图可以看出,在1.5s-2.0s之间,存在几次Render和JavaScript丢帧从多出的红点可以看出页面jank次数,也能够定位到代码堆栈   

在优化的过程中需要更多地思考,如何让阻塞的脚本分批执行,如何将长时间执行的脚本均匀地分配到时间线上。这些优化都体现在代码的细节上,宏观上的处理难以有明显的效果。当然,在宏观上,淘宝首页也有一个明显的优化:   

  //https://gist.github.com/miksago/3035015#file-raf-js   (function(){   varlastTime=0;   varvendors=['ms','moz','webkit','o'];   for(varx=0;x这段代码基本保证每个模块的初始化都是在浏览器空闲时期,减少了很多不必要的丢帧。这个优化也可以被应用到每个模块的细节代码之中,不过优化难度会更高。   

小结   

代码的性能优化是一个精细活,如果你要在一个庞大的未经优化的页面上做性能优化,可能会面临一次重构代码。本文从淘宝首页个性化引出的问题出发,从微观到宏观讲述了页面的优化实践,提出了几条可以借鉴的优化标准,希望对你有所启发。优化的细节点描述的不够完善也不够全面,但是都是值得去优化的方向。   

希望本文能帮助到您!   

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)   

  

关注{我},享受文章首发体验!   

  

每周重点攻克一个前端技术难点。更多精彩前端内容私信我回复“教程”!   

  

原文链接:https://fed.taobao.org/blog/2016/04/06/optimize-in-tbhome/   

  

作者:阎王(淘系前端团队)   

上一篇618活动满200减20(618满200减30到什么时候)

下一篇淘宝比价(淘宝比价)

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~