前言
- 无中心: 没有中央控制节点,可以自由的在网络发布任意内容。
- 无歧视:所有网络参与者可以平等的进行交流,不受操作系统,网络运营商,等等的影响。
- 自下而上设计: 鼓励大家参与和实验,而不是由一小部分专家编写和控制。
- 普遍性:所有人都可以在网络上发布任何东西,不受硬件,地理位置,信仰文化,等等的影响。
- 共 识:大家可以自由的参与规范的讨论,但必须遵循已形成标准的规范。
正是这种自由平等开放共享的精神,使得Web面对各种挑战,依然能一次又一次的焕发生机。
而在Web技术的应用过程中,我们往往会忽略这些内在的精神,更加关注一些更加具体的指标,比如性能指标。
在性能指标方面,前端往往缺乏非常精确的衡量手段,但几乎都会得出Web性能不如Native性能的结论。
然而事实真的如此吗,Web在各个方面都比不上Native吗?
从技术的角度来看,Native App可以直接运行在操作系统上,可以直接调用系统API,而Web App (or Page) 只能运行在浏览器,通过浏览器去调用系统API。
通过浏览器去调用系统API,这中间流程的性能损耗处于什么级别呢?很小,C++/Java代码执行的成本非常低,整个调用流程一般在毫秒级别。
那么,我们为什么会得出Web性能不如Native性能的普遍结论呢?
可能有下面几方面的原因:
(1)Web页面需要运行在浏览器上面,而浏览器的执行流程对前端来说是一个黑盒,在不了解这个黑盒的损耗的情况下,只好假定它的损耗是非常大的。
(2)一些前端框架的性能并不理想,特别是一些框架的初始化特别耗时。框架的执行流程对前端来说也是黑盒,框架的性能也会笼统的认为就是浏览器的性能。
(3)Web技术的使用方式灵活多样,不同的使用方式效果差别很大。一些Web技术使用不当,也可能会引入性能问题。
那么,怎样才能更好的使用Web技术呢?我们下面重点讨论一下,在进行前端优化时,我们可以有那些思路。
优化的基础
(1)精确的指标衡量体系
我们在进行Web优化之前,首先要做一些基础的事情,比如,建立能准确体现用户体验的指标衡量体系。
如果衡量指标不精确,优化效果可能会与我们理想的目标背道而驰,甚至会出现指标表现一片大好,而用户却处于水深火热之中的情况。
在首屏性能指标体系方面,UC浏览器一直走在行业的前面,主要表现在:
(1)行业内很多公司使用实验室数据作为指标数据时, 我们就早已使用真实用户统计数据作为指标数据。
(2)在内核层面使用自有算法去计算首屏性能,精确度非常高,远高于Chromium的First Meaningful Paint。
注:iOS 未开放内核, 所有浏览器只能使用系统内核,所以iOS上还未能实现UC浏览器的首屏性能指标。
出于多端指标统一的考虑,业务方往往会选择 WebViewClient.onPageFinished 或 PerformanceTiming.loadEventEnd 作为页面性能的衡量指标。
虽然这些指标不能很精确的衡量首屏性能,但也能成为多方可接受的折中方案。
目前UC浏览器也在与业务方一起建立一套统一的指标衡量体系,希望大家能在标准统一的情况下进行业务的优化。
(2)明确约束条件
我们在进行Web优化时,需要明确一些约束条件,在满足约束条件下达到指标最优。
比如,我们使用loadEventEnd作为页面性能指标,但这个指标仅仅反映了资源加载的性能,并不能反映首屏渲染的性能,或者用户可交互的性能。
我们不能为了提升loadEventEnd,将所有的资源都优先加载,而阻塞了页面排版渲染。即需要在首屏性能(T2)不变差的前提下去优化loadEventEnd。
再比如,我们都知道,资源预加载到本地,将联网性能转化为本地性能是优化性能的重要手段。但是,预加载一般会存在使用率不高,服务器压力过大等等问题,即我们不能为了提升100ms的性能而让服务端增加100台服务器,而应该在服务器部署成本不提升的情况下去优化性能。
初级优化
我们在进行Web优化时,需要分阶段有步骤的进行。我们先聊聊初级优化。
初级优化,并不代表简单或者不重要,而仅仅代表它是其它优化的基础,有比较成熟的优化实践指导方案。
初级优化一般是指正确使用Web技术和前端架构,包含但不限于:
(1)使用恰当的前端框架。
(2)使用恰当的前端技术架构。
(3)使用恰当的Web技术。
(4)按规范使用Web技术。
(5)正确使用Cache和压缩图片。
我们举了一些例子进行说明,
权威统计机构Http Archive的数据表明,所有页面的平均数据, 图片占页面大小的50%以上,其中压缩率比较高的WebP格式图片仅占1%, JPG+PNG+GIF图片占比96%。
我们业务的例子,2016年奥运会期间,UC信息流一些图片使用了未经处理的PNG图片,甚至有大小超过5M的单张图片。
我们再看看Cache的数据,Cache有效期为0,即不能缓存的资源,占比50%。这个比例是非常惊人的,即平均每个站点有一半的资源是不能缓存的。
这些看似简单基础的事情,大部分页面都没有做或者没有做好,会严重影响页面的性能和用户体验。
我们再聊聊前端框架,在使用前端框架时,需要先了解它的性能,特别是初始化性能。参考:前端框架启动速度对比
举个例子,滴滴出行页面,app.b6a92cf724d79c664f2f.js 执行耗时可超过1.5秒,主要是框架的初始化耗时,
- Line 735: 06-26 16:49:44.230 E/test-js, ScriptController::evaluateScriptInMainWorld, enter, sourceURL:(26731): https://shield.xiaojukeji.com/webapp5.0-homepage/js/app.b6a92cf724d79c664f2f.js
- Line 1664: 06-26 16:49:45.931 E/test-js, ScriptController::evaluateScriptInMainWorld, leave, sourceURL(26731): https://shield.xiaojukeji.com/webapp5.0-homepage/js/app.b6a92cf724d79c664f2f.js
各种前端框架都有它的初始化成本,我们一般需要选择合适自己业务要求,性能又还可接受的框架。
出于各种原因,比如一些历史原因,或者业务原因,我们很可能选择了性能较差的框架,我们也需要了解它的详细性能数据,做到心中有数。
中级优化
中级优化,一般是指结合业务场景,灵活使用数据和工具,定位和解决页面存在的问题。
各种页面在各类业务场景下,存在的问题往往都不一样,需要具体问题具体分析。
但分析问题的方法或手段都是相通的,包含但不限于:
(1)综合分析用户数据,挖掘问题。
(2)灵活使用Chrome Devtools 开发调试工具, 调试页面和定位问题。
(3)灵活使用 Lighthouse,检测页面和解决问题。
用户数据,是真实反映用户实际情况的。用户数据的分析也非常有讲究,各种分析维度都会得出各种结论,要合理的使用恰当的分析维度。
比如,用户手机系统,网络类型,地理位置,等等。
Chrome Devtools 开发调试工具 是前端开发调试神器,里面包含的功能非常强大,几乎能分析所有前端的疑难问题。
我们提取一些特色功能进行介绍,
(1)Timeline
Timeline可以记录页面运行过程的所有细节,能用于分析页面出现问题的具体位置。
举个例子,UC信息流页面,在2016.8.5页面改版之后,页面首屏渲染时间(T2)变长200ms。
改版前的Timeline是这样的:
改版之后的Timeline是这样的:
原因是一些期望在T2之后执行的JS逻辑,在T2之前就被执行了,从而延后了T2的渲染时机。
出现问题的代码:
_article.main(function() {
_article.fsTime();
cb && cb()
});
修改也很简单,将一些非首屏的渲染逻辑延后一些执行:
_article.main(function() {
_article.fsTime();
setTimeout(cb,20
);
});
当然, 上面只是使用Timeline的一个简单例子,与页面执行时序相关的问题,都可使用它协助分析。它的更多优秀功能,需要大家自己去探索发现。
(2)Profile
Profile 也是一款很强大的分析工具,它可以分析页面的内存使用情况和JS/CSS执行时间。
一般地,我们可以使用Timeline定位出现问题的大概位置,再使用 JavaScript CPU profiler 详细分析每个JS函数的执行情况,找到具体的问题点。
(3)Chrome Trace
Chrome Trace 数据记录了页面在浏览器内核执行的完整过程,粒度精细到每个函数方法。使用Trace数据可以分析页面在浏览器内核执行的细节。
根据Trace信息,可以很准确的定位具体的问题,前提是前端同学能够理解具体的函数方法在浏览器内核中的含义,所以对前端的要求是非常高的。
正因为Trace分析对前端的要求过高,Chrome又推出了基于Trace的分析工具Lighthouse。Lighthouse能根据特定的模型用例,得出前端易懂的分析结果。
比如,它可以检测页面是否符合PWA的要求,分析页面在关键路径的耗时。
UC浏览器针对Lighthouse进行了扩展,能够更加全面准确的分析前端关注的问题,比如,它能分析页面JS执行的总体耗时,超过50ms的JS执行函数,页面缓存命中情况,LocalStorage使用情况,排版渲染执行情况,等等。
针对业务所在的业务场景,进行一些定制的优化,往往能带来巨大的性能提升。比如,一些客户端的业务特别集中,页面非常稳定,那么,就可以使用提前下发离线压缩资源包的方式,让关键资源都从本地读取,加速页面的加载性能,和减少网络错误。
高级优化
前面讨论的优化,主要参与者是前端,主要受益者是分析者自己的页面。更高级的优化应该是怎样的呢?
高级优化一般是指全链路拉通进行优化,优化前端页面/框架,后端服务器/中间件,内核,图床,等等,并将优化结果集成到工具,形成自动化检测案例。
我们先来看为什么全链路拉通很重要。每个端(前端,后端,中间件,图床,内核,等等)都有自己的视角,很难看清楚整个链路的问题。
而页面性能问题可以发生在链路的任意一个节点,问题的解决方案在各端都有区别,通过全端拉通我们可以选择最优的解决方案。
举一些例子,
(1)在UC信息流优化过程中,我们多端拉通得出了一个首屏图片预加载的方案,改动涉及到页面,服务器端,图床,浏览器内外壳,最终提升整体性能近300ms。
(2)在支付宝H5性能优化过程中,我们与支付宝容器,网络库,多端拉通,最终分析出支付宝容器和托管网络库存在性能问题,修正问题后带来较大提升。
(3)在UC自媒体页面优化过程中,我们与页端,运营端,多端拉通,最终分析出运营一些配置使得页面文档无法缓存,而这个问题是可以避免的。
这样的例子还有很多,都说明了多端拉通在性能优化中具有非常重要的作用。
多端拉通进行优化,我们的视角更加全面,解决问题的思路也更加开阔。选择在最合适的端进行解决问题,解决问题的方法不再局限于修改前端页面。
我们也可以加强浏览器与前端的交流合作,在浏览器内核或前端框架层面,进行更加高效的优化。
前面也提到,一些前端框架的性能并不理想,我们期望与前端合作,一起去优化一些流行的前端框架的性能。
页面优化,通常属于一种补救手段,而不应属于一种常态,我们不期望同一页面的性能需要反复优化。
我们期望一些优化成果能够固化到工具层面,通过工具自动化去监测页面性能,让工具去保障页面能够持续具备优异的性能。
展望未来
前面重点讨论了前端优化的一些思路,我们再回到Web技术发展前景的问题。
Web技术所推崇的自由平等开放共享的互联网精神,得到了全世界的普遍认可。在Web技术发展之初,就由万维网发明人Tim Berners-Lee 带领成立了万维网联盟(W3C理事会)。W3C致力于构建广泛参与的、知识共享的、具有信任的全球规模的Web。目前W3C成员已经有超过400个研究机构或组织,其中包括Apple, Inc.,Google, Inc.,Microsoft Corporation 等全球顶级科技公司。有成千上万的科学家参与Web标准规范的制定和实现,我们有充分的理由相信Web技术的长远发展是有坚实的技术和人才保障的。
回顾历史,PC年代早期,大家都去下载Windows软件,随着PC电脑的不断进化,网络带宽的不断增强,现在大家很少会下载PC软件,基本以浏览器为主。
移动互联网时代也是一样,目前手机内存3G及以上的占比已超过50%,WIFI+4G网络占比已超过90%,手机处理能力和网络带宽已不是Web技术的瓶颈。
Google Chrome 在2014年推出PWA系列技术,给前端开发者全面开放浏览器的底层能力,包括但不限于,消息推送通知,拦截资源请求,管理资源缓存,添加到主屏幕,在合成器线程上同步运行用户代码,等等。
iOS Safari 在2018.2发布的Safari Technology Preview Release 49宣布正式支持Service Workers。主流浏览器都会全面支持PWA相关技术,前端能在Web上面发挥的空间会越来越大。
Web技术的繁荣发展,需要每一个开发者的共同努力,包括前端,浏览器,服务器。特别是前端开发者,前端每一次技术选型,每一个页面取得的效果,都与Web技术发展息息相关。UC浏览器期望与前端开发者紧密联系,共同打造繁荣的Web生态。