昨天在腾讯大厦参与了鹅厂AlloyTeam召开的AC2015前端大会,度过了充满精彩和收获的一个下午,用一句话形容这次前端Event应该是“诚意满满,干货满满”。
说实话,这次AlloyTeam没有对与会人员做严格的身份认证,基本到了就能参与,因此整个腾大的多功能厅下午是爆满了人。我去的其实算早了,却也只能抢到很后面的座位。许多去的晚的同行都只好站着或坐地板上参与。
本次AC大会也做了全程的官方视频录制,据悉后续将在慕课网上线,届时有兴趣的朋友可以去关注下。
大会起始环节是一个神秘项目的首秀—— 一款H5游戏坦克争霸(TankStrike)的公开,它的线上地址可以戳这里体验。
坦克争霸是一款挺全面也颇具特色的web游戏,你可以选择不同属性的坦克(有的血量厚,有的速度快)来应战,战斗时也除了常规的开火还能打出定位导弹,能根据敌方坦克的移动而修改自身弹道方向。
具体的玩法和特性就留给大家去线上体验了,这里不赘言,作为腾讯内部玩H5玩的最溜的AlloyTeam来说,能开发出这样优秀有趣的作品倒也情理之中。
接着是 show girls 们来拉动现场气氛了,据说都是我厂可爱的妹子们~
有一种团队叫AlloyTeam+
这是第一个分享环节,由 AlloyTeam 的 Leader 于涛主持,介绍了此次召开AC大会的初衷——AlloyTeam每年都有许多酷炫好玩的开源项目,希望每年都能有这样的机会跟大家一同分享。
这意味着后续每一年,AlloyTeam都会召开一次AC大会,作为深圳的一次前端盛事了(不过还是建议明年好好验下参会者身份嘛,不然对早早报名了的朋友不太公平)
于先生接着做了前端行业趋势的分析,如PPT所示是酱的,看着是机会多多:
当前前端领域的工程师可以说是越来越多,因此才能招到漂亮的女神妹子来撸码,不过他也因此抛出一个看法—— “市场不是缺少前端,而是缺少优秀的前端工程师”。
随着前端领域技术点的日益丰富,前端行业虽然入门简单,却存在深入难的瓶颈,因此鼓励大家做到“精于业务而不限于业务”。
另外于先生也分享了其对当前行业技术趋势的归纳——”移动化“和”复杂化“,表示当前前端技术已逐步渗透到移动端领域,我们还可以利用它来完成许多复杂的动画和游戏。
接着是向与会者介绍了 AlloyTeam 团队,包括名字的寓意、团队的规模和运作方式等,也介绍了这些年来 AlloyTeam 的一些重要的开源项目,包括应用在web QQ上的JX框架、CodeTank在线(玩)学(游)代(戏)码平台、H5体感游戏“墙来了”、H5专业级图像处理引擎AlloyImage、 AlloyStick骨骼动画引擎等,也透露了16年的主要研发项目为在线创作平台iPresst和在线动画创建平台AlloyAnimation。
最后于先生表示将在未来开启“+计划”,把AlloyTeam团队开源,做第一个“无边界的开放技术组织”,有兴趣有能力的小伙伴可以加入成为AlloyTeam的合作伙伴,拥有参与项目的机会,从而同步获得更多AlloyTeam的资源和技术经验,还有机会进入AlloyTeam的名人榜呢~
我有我特色——开发眼中的移动交互
第二个分享环节是号称”老教授“的潘佳韩主持,他把简单的页面拆分为MVC模式——M代表”HTML",V代表“CSS",C代表”JS“(就一个比喻,不要跟我们常规说的MVC框架搞混了),从这个角度来厘清PC web开发与移动web开发的差异(交互角度上)。
老教授针对不同案例都录制了一些交互对比视频,主要是”点击“和”长列表滚动“俩种行为的交互对比,从而讲了一些基础概念、常见交互问题和解决方案。
1. 点击交互
鉴于很多PC web的页面是没有针对浏览器来做移动开发的,所以当用户用移动设备访问这些页面时,经常需要通过手势来放大缩小视口中的内容,为了方便,常规移动端浏览器都提供了双击放大/缩小视口内容的功能,因此,浏览器对”click“点击事件做了300ms的延迟来区分单击和双击事件(如果没有延迟,双击的第一击可能就触发了其它的行为)。
但是当你的页面已经是基于移动端来做开发的,这300ms的延迟就显得多余了,会让很多单击事件显得滞后,造成糟糕的交互体验。
常规我们会使用 zepto 的 tap 事件来替代 click,tap 实际上是由 touchstart、touchmove、touchend 三个手势事件来协调完成事件判断是否触发的——当用户手势滑动距离够短、时间足够快,那么就触发对应的绑定事件。
不过话说这里到没提到常用的 fastclick~
另外在交互优化这块也建议我们要关注点击态的反馈——用户点击的瞬间要有及时的外观反馈。
我们常常会利用 :active 伪类来设置某元素被点击时的点击态样式,但也存在一个问题——滚动页面的元素的时候也会触发该反馈。建议的解决方案却也简单:点击元素时动态给其加上带点击态的class,再在150ms后动态去掉该样式。
2. 长列表滚动
开始先抛出了两个概念——”全局滚动“ 和 ”局部滚动“,前者指滚动条位于body或更顶层,后者指滚动条位于body下的某节点内。
然后是写样式最常遇到的滚动问题了—— ios在”全局滚动“的情况下默认开启弹性滚动特性,但在”局部滚动“的情况下则不开启,导致滚动内容时显得非常干涉。
建议的解决方案如下:
body{-webkit-overflow-scrolling:touch;} /*子节点会继承*/ .scroll-elm{overflow:auto}
另外ios在滚动时还容易出现一个出界bug——已经滚到边缘时再继续拉动会拉出一些没内容的空白区域,这个区域的背景色还很可能跟滚动列表的背景颜色不同:
就此ios 滚动bug的解决方案有:
⑴ 引入 scrollFix 解决(具体查看这篇文章;
⑵ 全局滚动改为局部滚动,页面的固定区域禁止touchmove默认事件;
另外关于”出界“部分背景色跟滚动列表不一致的,老教授建议不要直接设置滚动元素的背景色,另外说了个好消息——ios8开始,safari出界部分的背景色已经可以和 body 背景色保持一致。
至于安卓设备,其在局部滚动的情况下可能会存在反应滞后、滚动条断开的bug,因此老教授建议安卓页面尽量都采用全局滚动的页面结构。
那么当你的页面有上下固定、中间滚动的需求时,应当如何将其作为全局滚动的形式呢?机智的老教授给了答案:
话说这里其实我也存在一个问题——安卓和ios可能需要匹配不同的样式来做滚动优化,那么如何做一套样式匹配两种情况呢?
刚好后面的问答环节有人问到同样的问题,老教授表示可以在一开始时通过ua识别来给页面html标签加上对应的样式(比如 class='ios-style'),以这种形式来让页面节点获取到对应的样式(比如 .ios-style div{...})。
点击和滚动的交互优化讲完,老教授开始分享”键盘定制“的交互优化——通过不同场景出来不同键盘:
建议开发时依据场景给 input 标签设定好对应的 type 值(url / email/ tel / number / search)来拉起对应的键盘。
不过注意在 ios9 中使用 type='search' 的情况下,要求 input 得挂在 <form> 下才会展示出对应外观,所以常规就是乖乖裹层带有 action 的 <form> 然后禁用 onsubmit 的默认行为。
此处也简单介绍了pattern特性的使用:
另外有时候设备会在你输入英文名称时默认首字母大写,或者在你输入英文词汇时启动自动纠错(底部出现波浪形),这两种默认开启的功能可以通过配置 autocapitalize='off' 和 autocorrect='off' 特性来关闭。
时间都去哪了——移动 Web 首屏优化实践
该环节由高级前端工程师 Johnny 郭碧青主持,开始时抛出了一些问题和首屏时间的概念,然后开始讨论影响首屏加载时间的因素,包括DOM与资源的加载、解析和渲染,还有网络过程中的耗时:
其中 RTT 表示 Round-TripTime,即“往返时延”,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。
关于不同网络环境下的RTT,Johnny 分享了一些数据:
通过数据研究可获得一个结论——web页面在网络上的耗时总是远大于浏览器(解析渲染资源、执行脚本等)耗时的,因此针对网络耗时的部分来着手优化是减少首屏时间的关键。
关于页面测速的方法,Johnny也分享了两种原生实现—— Navigation Timing 和 Resource Timing 。
后续就是实打实的一些优化方案了,主要包括了如下建议:
⑴ DNS预解析
即预先解析那些用户后续可能会访问到的域名,这样用户再访问那些页面的时候可减少DNS的解析耗时,使用的是H5的 prefetch 特性:
<meta http-equiv=”x-dns-prefetch-control” content=”on”/> <link rel=”dns-prefetch” href=”http://a.qq.com”/> <link rel=”dns-prefetch” href=”http://b.qq.com”/>
⑵ 域名收敛
说的简单点就是单条请求获取多个资源,该方案在腾讯内部应用的还是挺多的。
这里举个例子吧,比如下面这条请求就一口气返回了对应的多个脚本资源:
http://imgcache.gtimg.cn/c/=/club/qv/pkg/qv_1.x.x.js,/clubact/premin/jquery.webStorage.min.js,/clubact/common/oz.js,/clubact/common/aid.js,/clubact/common/mustache.js,/clubact/common/nav/youxi_nav.js
⑶ 链路复用
这里主要是针对网络耗时所做的优化,具体方案为开启长连接(keep alive)功能:
也提及了未来的 http2.0 规范,随着长连接的普及可以减少很多耗费在RTT上的时间。
不过这里没有提及SPDY,虽然是被抛弃的货,但还没有彻底退出市场(腾讯内部其实也开过几次SPDY的课程)。
⑷ 组件化开发
鼓励页面资源按需异步加载和渲染,最好能先在服务端(Node)做渲染处理,这块属于直出的概念了。
另外也建议前后端组件同构(React的服务端渲染会是个好例子)。
⑸ 资源加载优化
例如利用webpack进行打包,再通过页面路由按需加载/卸载相关资源。
⑹ 图片懒加载
<img>插入DOM树时先进行可视区域计算,如果不在可视区域则 scroll 后再赋予src。
⑺ 缓存利用
详尽一切变态方法来利用缓存,就手Q这个客户端而言,企鹅做了不少的优化,包括缓存页面上次访问的数据(下次打开时先复用该数据,再做cgi请求来更新),还有离线包。
这里也介绍了兴趣部落页面的数据缓存框架:
也顺道举了个例子,部落首页获取到的帖子标题、作者和点赞数,可以先存到本地(localStorage),用户打开该帖子时先直接从缓存去复用这块数据,然后再通过cgi请求做更新,减少白屏时间:
⑻ 离线包
也是手Q客户端独有的功能,可以将业务资源永久地保存在本地,用户取相关资源时直接从离线包去取,而无须发送http请求。
不过这块仅支持公司内部业务,并未对外开放接口。
参会者“五分钟”分享
该环节共有三位同行做了精彩的分享,分别是“逐帧动画的像素差优化”、“React单页面性能调优”和“前端心路历程”。
“逐帧动画的像素差优化”的目标主要是尽可能地压缩图片资源的体积,当我们走css3逐帧动画时难免会用上一张体积很大的雪碧图,那么可以通过对比雪碧图里不同帧的图像的像素差,再组成仅由像素差合成的雪碧图来作为动画背景,可以大大减少雪碧图大小。
个人觉得这个想法比较新颖,但执行起来会比较困难,不太清楚有没有啥生成像素差雪碧图的自动化工具。该分享后续本来提供了个微信二维码让与会者扫一扫加入了解更多该方案,但鉴于五分钟的时间太短,我才打开微信他就被“请”下去(PPT也关了)换另一位分享者了,这个还蛮遗憾的。(p.s. 后续跟作者要到例子拉,大家可以看看)
“React单页面性能调优”的分享主要提及路由切换时,若页面虚拟DOM较多的时候,它们的切换会存在性能问题,然后分享了一些建议,比如以计数路由的形式来决定虚拟DOM是否做卸载处理(怎么有点像以往的JS垃圾回收机制呢):
不过五分钟时间太短没法了解的详细,看下他的总结吧(坐的很后面所以都是放大拍的照片,糊是一定的):
“心路历程”的分享者米爱个人风格蛮幽(浮)默(夸),一开始还以为他来踢场捣乱的,不过后面发现他讲的还是挺有意思,PPT也做的很用心。
手Q Hybird App 优化之路
由前端高级工程师赖晓思主持,主要分为“首屏数据展示耗时优化”和“长列表滚动优化”俩部分。
首屏数据展示耗时优化部分主要是建议首屏的数据尽量不要依赖cgi请求,例如利用 localStorage 缓存数据来做优先展示.
这里取了兴趣部落缩略图缓存的例子,即帖子打开的时候,优先显示首页所用过的小图,然后再通过cgi去取大图,减少白屏时间:
鉴于图片均配置了较大的 max-age 缓存设置,所以短时间内重新拉取图片时是不会再发送http请求的。
接着也是介绍了手Q这个自主研发的客户端的一些优势,比如使用了 mqq 这种集成在手Q内的 native 组件,在页面使用时会先通过js判断用户当前环境,如果是手Q访问则直接调用 native mqq,否则才发请求去下载远程资源。
另外鉴于客户端上打开一个新的 webview 是比较耗时的事情(安卓平台可能会有1.5-2.3s的空白等待时间),如何利用这块时间是值得思考的事情。
就此 mqq 组件提供了 dispathEvent 和 addEventListener 接口,可以在绑定webview创建/销毁时的事件,从而得以在webview创建的时候预先去拉取cgi数据。
接着是长列表滚动的一些优化。先是分享了一些业务视频,对比各个滚动方案效果,并逐步做了这些建议:
⑴ iscroll 的滚动性能较差(会不断监听滚动事件并触发回调),当数据较多时很容易造成卡顿(特别在安卓上)
故建议避免使用iscroll,而是以 div 局部滚动的形式来替代它,但该方案在滚动很快的时候可能会出现闪白的问题。
⑵ 依旧推荐使用局部滚动,不过把滚动层与内容层做分离——利用添加了 pointer-event:none 的元素可以实时触发scroll事件的特性:
不过该方案在部分设备(小米)中也存在内容跳动(而不是滚动)的问题,会让用户体验变得很糟糕,原因是 div 的 scroll 虽能被实时触发,但 scroll 过程中产生的样式变更要等到 scroll 结束后才被渲染。
⑶ 模拟滚动,且滚动的过程动态删除/新增列表中的DOM,防止节点太多导致的性能问题。但频繁的DOM操作会导致不断触发layout,配置低的机器容易卡顿。
⑷ 利用canvas绘制,这样页面上就只有一个画布元素了,此处的示例用了 canvasList。不过使用canvas也存在一些问题,例如当绘制区域较大时,FPS会明显降低,部分低配设备会不流畅。另外画布存在交互障碍的问题(无法直接获取上方的内容)。
⑸ 滚动过程复用dom。话说这也的确是终极方案了,这么做一来不会积累太多DOM节点,二来由于仅仅修改了DOM中的内容,也不会频繁触发layout。阿里的滚动组件也利用了这个概念。直接上张图吧:
最后是长列表滚动优化的总结:
源自手Q Web 的最佳实践——Abstract 前端开发生态
压轴环节吧,由 Dorsy 王斌主持,介绍了兴趣部落现在所应用上的 Abstract 框架,属于一个拨出衣服(HTML、css),只关注逻辑的框架,并把所有模块归纳为两种关系——“同时渲染” 和 “互斥关系”。
另外也介绍了其配套的类ng模板 sodaRender。
感兴趣的朋友可以直接去其官网了解下,这里就不多说了。
总结
整体来说这是一场精心准备的分享大会,带给了我们许多有趣和值得回味的干货。话说在 AlloyTeam 开源了多个项目后还能试着做更进一步、更深层次的技术分享可谓难能可贵,天朝的IT圈子还是很需要这样的分享、交流精神的。
也希望往后的AC大会都能愈办愈出色,只是弱弱地建议下,虽然开放给更多感兴趣的朋友来加入这次活动是好事,但挤掉了报名者的位置还是觉得不妥当。
另外短信最好温馨提示带只笔嘛,既然希望我们填写问卷,但只带电脑没带笔的孩纸伤不起,连纪念服都没的换有木有。
对了,如果能多搞几个排插给与会者的设备充电就更好了,我的傻多戴XPS撑了四小时直接没电扑街。。。
这次的汇总就写到这吧,后续官方也会挂视频上来,有兴趣的朋友届时可以再去看一看,个人还是非常推荐的。共勉~