作者介绍:Addy osmani
就职谷歌Chrome团队,致力于让网站运行速度更快,他参与的项目包括——lighthouse
随着移动互联网快速发展,移动端网站的页面效果也越来越绚,但是交互体验或多或少有些“迟钝”?这是为啥呢?
首先JavaScript运行在手机浏览器上会产生不小的系统开销,由于这个问题存在,Addy osmani 将会带着大家探讨移动端网站的脚本问题,让其在大多数手机浏览器上运行更快,更轻。
我们在构建交互式网站自然少不了JavaScript, 为了达到更好的交互,我们让用户浏览器加载了太多的JavaScript脚本。不知道大家是否有这样的浏览体验:我们在手机浏览器上刷网页,点击链接或者滑动页面时,网页一点反应都没。这种经历,想必大家都有,因为对于手机浏览器来说,运行加载JavaScript会消耗不小的系统资源,因此延迟了用户的交互响应,今天我将会给大家介绍一些有效的方法策略,提升用户在手机端的使用体验。
太多的“交互”,让网站更臃肿!
当你的用户用手机访问你的网站时,你的网站让用户的浏览器加载了大量的文件,其中很多是脚本文件。也许你为了方便开发或者为了更炫的效果,引入了脚本库或插件库,从来没有检查确认到底加载了多少脚本,体积有多大?加载的脚本是否对用户有用?对于我们多说前端客来说,我们是如此的喜欢JavaScript,但是我们不得不正视它会消耗不小的系统资源。
不少热门的网站,向用户的浏览器发送了大于1MB的脚本文件。只有为数不多的网站进行了脚本文件压缩,使脚本体积大小降到350KB左右,那些未压缩脚本的网站,如果脚本超过1MB大小,您的用户至少需要等待14秒的时间才能正常使用你的网站。(部分热门移动网站脚本加载分析报告:https://beta.httparchive.org/reports/loading-speed)
为什么这么慢?用户大多数是在不稳定的移动网络加载你的网站,脚本加载完了,需要手机CPU进行运行处理。
以下是目前大多数网站存在的问题:
- 使用了用户界UI框架(例如bootstrap)
- 客户端框架或交互依赖框架(React,vue)
- Polyfills(但是现代浏览器并不需要)
- 未压缩的脚本工具库(例如moment.js)
随着需求的增加,脚本的数量也在增加,体积也再不断变大,因此页面运行的时间也越来越长!
现代网页加载时...
一个网页加载时,对于用户来说:网页是否还在加载?加载的内容是否有用?功能是否能用?当网页的内容一点点呈现给用户时:导航显示一部分出来,服务器是否还在正常发送内容?当文本和其他非可见的内容,是不是用户需要的,内容加载完了,用户能否正常的点击和滑动?
所谓的交互式页面,必须快速响应用户的输入,因此javaScript脚本应该快速响应用户的交互,无论用户点击链接还是滚动浏览页面,用户都需要页面快速响应自己的行为。
为了最大化的满足产品业务需求,您可能要求用户的客户端运行很多事件,由于JavaScript语言的特点,主线程上的事件延迟了交互元素的呈现,对于许多公司来说缩短交互时间是一个不小的挑战。
什么才是好的交互目标?
我们Chrome团队认为,在大多数中等手机设备(https://calendar.perfplanet.com/2017/time-to-interactive-measuring-more-of-the-user-experience/),3G或4G的网络环境下,5秒内完成用户的交互响应,这就是良好的交互目标。你可能会说:我们的用户都是用高端的手机和使用快速的网络。但是我们所谓的用户呢?——在使用“快速”的咖啡店的共享wifi或移动的车厢里访问我们的网站,他们的手机实际只能获取2G或3G的速度。
哪些网站开始减少脚本的体积,缩短了用户的交互时间?
Pinterest.com 将原先的脚本从2.5MB减少至200KB以下,交互时间从23秒减少至5.3秒(https://medium.com/dev-channel/a-pinterest-progressive-web-app-performance-case-study-3bd6ed2e6154),正式由于这个改进,网站的收入增长了44%,注册量增加753%,移动网络用户的活跃度增长了103%(https://medium.com/@Pinterest_Engineering/a-one-year-pwa-retrospective-f4a2f4129e05);autotrader网站将脚本的体积减少了56%,缩短了50%的交互时间。(engineering.autotrader.co.uk/2017/07/24/…)。
对于一个移动网站时,不仅要考虑脚本的体积大小,响应时间,还要考虑移动变化不稳定的手机网络和大多数终端手机的硬件环境。
为什么JavaScrip的代价如此之高?
我们都清楚一个请求发送至服务器后,服务器会逐步返回一些HTML内容,在逐步解析渲染DOM时发现标记不同的资源(CSS,JavaScript)以及图片资源,然后完成这些文件的下载和处理。
如果要让JavaScript快速相应用户的交互,我们必须要让脚本快速的加载和编译执行,由于JavaScript需要快速完成编译才能执行用户的响应,这个过程必然会影响延迟用户的交互体验。
还有一点需要记住,网络上同等的资源,消耗的系统资源却不同。一个200KB的图片绝对不等于一个200KB的脚本消耗的资源,下载这些资源时间可能相同,但是消耗的资源成本却不一样。
不同类型的手机
现实就是这样,并非每个人都用得起高端手机,还有大部分用户使用中低端手机。由于中低端手机CPU,GPU的限制,处理JavaScript等资源的时间也不同。因此我们应该在真实的手机环境和网络环境下测试至关重要。检查分析您的用户访问行为至关重要,如果您无法购买太多中低端手机进行测试,你可以使用这个在线网站工具WebPageTest(webpagetest.org/easy),进行在线测试。(以下是小编前端达人www.qianduandaren.com的测试效果)
了解你的网站受众十分重要,并非每个网站都要满足低端手机在2G的环境下表现良好,你应该保证你的大多数用户快速加载你的网站。
如何减少JavaScript脚本的发送
Code splitting(代码分割)技术——将会帮你拆解大的JavaScript脚本文件,实现了脚本的按需加载(lazy-load)。这样有效的避免了将单个“main.js”整个站点的脚本文件发送给用户。
将代码引入站点的最佳方法是动态import(),相关介绍请点击查看developers.google.com/web/updates…,下面这个例子使我们常见的静态引入方法:
import {add} from './math'
console.log(add(30, 15)); 如果使用动态import(),我们可以按需加载引入math脚本文件,例如实现点击一个按钮动态引入math脚本
const btn= document. getElementByld('load);
btn.addEventListener('click',()=>{
import('./math').then(math =>{
console.log(math.add(30, 151));
});
}); 使用webpack构建的项目也能很方便的实现按需加载,具体如何使用可以点击查看www.jianshu.com/p/b3b8fb8a2…这篇文章。代码分割同时可以应用在路由加载、组件加载、页面加载等方面,以下分别是使用React,Vue,Angular使用Code splitting的使用指南:
- React——medium.freecodecamp.org/code-splitt…
- VueJS——router.vuejs.org/zh/guide/ad…
- Angular——angular.io/guide/lazy-…
如果你正在使用React,我很高兴向您推荐推荐React Loadable(github.com/jamiebuilds…),实现了动态高效的加载组件,以下代码是我们使用静态方法引入gallery组件:
import GalleryComponent from ‘./GalleryComponent’;
const My Component=()=>(
<GalleryComponent/>
); 使用React Loadable后,我们改下上面的代码:
import Loadable from 'react-loadable’;
const LoadableGallerycomponent=
Loadable({
loader: ()= >import('./GalleryComponent'),
loading: ()=><div>Loading...</div>,
});
const MyComponent=()=>
<LoadableGalleryComponent/>
); 最近许多大型团队正在使用Code splitting方法改写重写他们的手机端网站,并取得巨大的成果。比如Twitter他们背后优化的故事——blog.twitter.com/engineering…,Tinder背后优化的故事——medium.com/@addyosmani…,他们都通过此项技术将交互时间缩短了50%。
Next.js[react](github.com/zeit/next.j…),Preact CLI(github.com/developit/p…) ,PWA starter kit(github.com/polymer/pwa…) 这些框架设计之初的首要目标就是解决移动端网站的性能问题,让代码快速加载响应用户的交互。
值得庆幸的事情,JavaScript生态为我们提供了分析打包后所有组件与组件的依赖关系的可视化工具,帮助我们分析。比如:
- Webpack Bundle Analyzer( www.npmjs.com/package/web…)
- Source Map Explorer(github.com/danvk/sourc…)
- Bundle Buddy (github.com/samccone/bu…)
优化,监控
如果你不确定你的JavaScript性能是否有问题,你可以使用Chrome提供的Lighthouse——是一个Google开源的自动化工具,主要用于改进网络应用(移动端)的质量。目前测试项包括页面性能、PWA、可访问性(无障碍)、最佳实践、SEO。Lighthouse会对各个测试项的结果打分,并给出优化建议,这些打分标准和优化建议可以视为Google的网页最佳实践。
还有一件值得你监控和关注的事情,就是检查有没有将未使用的代码发送给用户, code coverage(developers.google.com/web/updates…)——谷歌浏览器开发者工具中的代码覆盖率面板,此面板内会告诉你哪些代码未使用,哪些又是使用了的。这样可以精简掉未使用的代码来减小页面的大小。
这些工具对于识别需要分割代码及哪些需要延长加载非关键脚本是非常有价值的,庆幸的是有一套标准的评估指标指引优化——timkadlec.com/2014/11/per…
设计合理的优化指标
定义一个可衡量可测试的优化目标至关重要,有个标准的行为指南有助指引整个团队围绕着目标不断的改善用户交互体验。指标主要包含以下几个方面:
- 里程碑时间——页面加载完,具备响应用户的时间。
- 数量指标——JavaScript脚本大小,多少文件请求数,图片数量和大小
- 基于规则的指标分数——我们可以通过专业的工具Lighthouse或WebPageTest等工具进行相关的评分。
绩效指标对于团队来说,最大的挑战并不是技术而是公司的文化,我们需要开会不断的围绕目标进行讨论,向业务运营团队咨询他们期望的目标并接受各种相关质疑,同时向工程技术人员传达会议目标让其解决瓶颈问题,虽然过程有些痛苦,但是对项目的推进还是有很大的帮助。
那么有什么样的工具能够帮助我们决策制定合理化目标并生成可视化的报告呢,你可以使用 lighthouse CI project (github.com/ebidel/ligh…),Calibre(calibreapp.com/),treo(treo.sh/),speedcurve(speedcurve.com)
快点、再快点
许多小的改变将会带来巨大的收益,尽可能的减少JavaScipt的体积换取更短用户交互时间,如果你能渐进式的逐步推进这个目标,你的用户会十分感谢你。
更多精彩内容,请微信关注”前端达人”公众号!
新年大礼包
关注“前端达人”公众号,回复“新年大礼包”获取英文电子书:
更多精彩内容,请微信关注”前端达人”公众号!