我们的最佳实践正在扼杀移动 web 性能

Posted JavaScript

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我们的最佳实践正在扼杀移动 web 性能相关的知识,希望对你有一定的参考价值。

本文转载自:众成翻译 
译者:huangxiaolu 
链接:http://www.zcfy.cc/article/430 
原文:http://molily.de/mobile-web-performance/


在移动领域,为桌面 web 而生的性能规则需要重新修订


前言


几年前, web 开发者 Nicole Sullivan 发表了一个颇具影响力的演说:我们(CSS)的最佳实践正在扼杀我们。Sullivan 曾经作为先驱之一,为可预测、可维护、大规模的 CSS 制定了规则。


Sullivan 在 2011 年的演说中谈到,人们过去所认为的 CSS 最佳实践其实阻碍了我们。她以 OOCSS 发起了一项运动,最终市面上出现了像 Bootstrap 和 Foundation 这类框架,还有 SMACSS, BEM, CSS modules 以及内联 CSS 等方法。现在,前端开发领域都致力于创建可重用和封装的组件。 Sullivan 帮助世人形成了“乐高积木”式的理念。


本文不会谈论结构化 CSS,但是我会借“最佳实践有时候会伤害我们”的思想,解释移动 web 开发中的这种现象。


移动 web:更差的用户体验


如今移动 web 访问已经很普遍了,对大多数人来说,这是第一次也是唯一的 web 体验。我每天都会使用 web,用的是一个功能强大的智能手机,在 EDGE 或者 HSPA+ 网络下。但是总体的用户体验让人抓狂。作为一名用户和开发者,我发现相对于桌面浏览器,移动浏览器实在是不可靠,还很慢。为了改善性能,减少数据流量,我几乎一直使用基于代理的浏览器 Opera Mini。


有无数的文章吐槽移动 web。有些文章指责移动 web 浏览器,有些指责创建者、web 开发者或者广告商。这些文章说的很有道理,整个产业都有责任。Web 网站加载慢,响应也慢,因为它们太臃肿了:各种耗时的广告脚本,高清大图和视频,太多定制字体,庞大的 javascript 和 CSS 框架(尽管网站只用了其中的十分之一)。


以上错误,有些只需基本的性能优化就可以随时修复。有些则需要在概念和设计阶段就阻止掉。还有一些需要将通用代码替换成定制裁剪的代码——对于小型网站来说,这种方案不太现实。


现阶段的性能目标和方法


在低带宽、高延迟的移动网络连接下,相对于高带宽、低延迟的有线网络连接,web 网站会加载得更慢。但是主要问题不在于网页完全加载所需的整体时间,而是网页在加载期间的行为。


响应时间和输入(交互)反馈对于用户感知到的性能影响最大。因此,web 网站要努力优化“开始时间”。也就是说从开始请求到初次渲染到屏幕上的时间间隔要尽可能短。用户应该在很短时间内就看到有用的信息。并且初次渲染的外观应该接近最终的样子。这也是速度指数所衡量的目标。


我们曾花费大量精力优化“关键的渲染路径”。主要的优化方法就是延迟载入对初次渲染不重要的内容。这种做法带来的典型结果是大量的内容、样式,和行为都延迟加载了。


打扰用户交互


当用户看到首屏内容或者用用非视觉方式开始“阅读”网页时,他们就会开始与网页进行交互,比如向下滚动或者点击按钮和链接。他们会假定这些操作都会生效,或者假定网页已经稳定了。


不幸的是,大部分移动网站都达不到用户的期许。在初次渲染后,内容还会改变和移动。新内容不仅会添加到末尾,还有可能会直接添加到中间。最常见的例子就是图片、视频、菜单、侧边栏、交互部件,以及广告栏。另外,定制的字体还会影响整体布局。


这些内容的变化不仅会困扰用户,打断正在进行的交互,还会造成布局回流(layout reflow)。也就是对元素的定位进行密集的重计算。在用户看来这些回流就像是“页面上的东西在跳来跳去”。


最让人崩溃的情况是用户已经向下滚动了,新增的内容却添加到了当前滚动位置的上面。浏览器只能通过更智能的滚动行为来尝试阻止这种“跳来跳去”


最佳实践正在扼杀我们


为什么移动 web 网站性能那么差呢?我认为是由于开发者遵从了最佳实践。假如他们不加思考,盲目遵从,这些最佳实践可能会扼杀性能:


  1. 延迟加载不重要的内容

  2. 渐进增强以及低调的 JavaScript(Unobtrusive JavaScript)

  3. 非阻塞、异步的 JavaScript


尽管我非常支持渐进增强,但是我认为我们理解得还不够全面,而且实践也需要持续地改进。渐进增强的基本思想是根据 web 设备的能力区别对待。


渐进增强使我们能聚焦到网站的核心功能上,它本可以提高性能。然而渐进增强被误解成了:_在用户看到的加载期间_进行增强。


当用户正在玩滑板时,滑板却突然变成了自行车,然后又变成摩托车,然后又变成汽车。并不是说用户不喜欢开汽车,但是当他们刚学会玩滑板,你却把滑板拿走时,他们会很恼火。


“低调的 JavaScript”是一种很老的技术,我已经在以前的文章里面评价过了。当我们向已经存在且功能完备的 html 结构添加额外行为时, 我们以为这样的 JavaScript 是“低调的”。但其实只要 JavaScript 运行起来,就会改变 HTML DOM 
,增加额外的行为。这将无可避免地导致明显的内容改变和回流。


在桌面电脑上,有着快速的网络连接,在初始渲染后数毫秒内,内容就能改变完毕。但是在手机上,用户会先看到无 JavaScript 版的网页,并且还可能跟网页交互,几秒后 Javascript 才会明显地将网页切换成增强版。


最近十年内,我们教育 web 开发者要异步非阻塞地加载脚本。有个基本的 web 性能规则是“将样式表放在HTML代码的头部,脚本放到底部”。


当把额外的 JavaScript 放到页面底部,或者将其标记成 async/defer 时,代码可能会_在初始渲染之后的任何时间_执行。在手机上,我们经常看到,等了不下10秒终于出现了用 JavaScript 实现的下拉菜单,固定的元素以及交互部件。


移动 web 性能指南


在这个移动 web 访问占主导地位的时代,以上这些实践会导致问题。有些本身挺好,但是需要结合具体情况使用。我并没有让大家完全弃用上述实践,但是在移动时代,我们需要重新修订这些规则。下面列出我更新过的一些指导方案:


1. 辩证地使用延迟加载


要清楚,延迟加载内容和延迟初始化组件是一把双刃剑。它会在提升用户体验的同时也伤害了用户体验。请明智地选择要按需延迟加载的内容。


2. 识别关键代码,忘掉经验法则


对于复杂网站,“将样式表放在HTML代码的头部,脚本放到底部”并没什么用。我们需要把最重要的内容和交互相关的 HTML,CSS 和 JavaScript 识别出来。这种关键代码会阻塞初次渲染。为了提高性能,甚至需要将样式和脚本内联到 HTML 中。


大多数 CSS 都不是关键代码,因为首屏不需要那么多样式代码。这些 CSS 可能是为了影响其它页的内容,所以没必要以阻塞方式加载它们。


有些 Javascript 很关键,比如主导航的代码。这种小脚本应该同步加载,这样用户就不会突然看到主导航像变形金刚一样出现了。


3. 不要打扰用户交互


当加载新的内容或者行为时,多次渲染页面区域是可以接受的。但是每次渲染都要提供一个_可用且稳定的接口_。用户的交互不应该被打扰到。一个接口控制器在用户与之交互的时候不应该改变页面。


4. 不要回流


应该选择_添加_内容而不是_改变_已经可见的内容。不要让回流影响已有的内容。有一个很简单的方式就是将内容添加到页面底部。这符合从上到下的自然的阅读顺序。


5. 支持滚动,固定高度


在页面加载时应该允许滚动,而不是干扰滚动。要避免滚动位置的跳跃。当内容延迟加载时,应该使用固定高度的占位元素,尤其是在用户到达滚动位置时。要么保留一个空白区域(比如,用来显示广告),要么展示一个标题或者加载器(比如,留给页面区块,侧边栏或者小部件)。


6. 测量并改进速度指数


首屏在页面加载期间不要有太明显的变化。确保在速度指数图上看到的曲线能够在很早就迅速上升到 90-95% 的视觉完成度,之后就保持一条平稳的线。


案例研究: BBC News 的文章页


我找不到一个实现了这些指南的复杂网站来。不过既然我是_通过反证_得出的这些指南,倒是可以举个值得改进的例子。


如今,大多数复杂的新闻网站的加载表现对用户都不太友好。来看看用 webpagetest.org 得到的一个 BBC News 文章页的性能测试 。测试设备是一台摩托罗拉 E,浏览器是手机版 Chrome,网络是模拟的慢速 3G 连接。


过程描述:回流,以及回流,还有回流


我对这个网站的加载性能进行了充分的检测,详细过程可以在这个幻灯片视图(http://www.webpagetest.org/video/compare.php?tests=160516_8J_19YF-r:1-c:0)以及这个视频里 看到。



幻灯片里放大的摘要


  • 首次渲染在 8 秒之后。文章内容已经完全可读。

  • 过了 10 秒,分类目录插入到头部和文章标题中间,引起了回流。

  • 过了 2 秒,分类目录变成了下拉菜单。

  • 出现了 8 秒的灰白屏。我没有在我的智能手机复现。我猜只是测试环境的问题。

  • 广告条插入到头部和分类目录导航中间,引起了回流。

  • 大约在同一时间,一个区块菜单插入到占位区域,没有引起回流。

  • 过了 5 到 6 秒,导航到 BBC 其它网站的下拉菜单加载进来了。它将原先页面底部一个简单的链接替换成了一个菜单按钮。

  • 在我真正的手机版 Chrome 里, 一个全页广告在页面完全加载后弹了出来。


评估:延迟加载误伤了性能


显然,BBC News 网站优化了初次渲染时间。延迟加载了图片,导航组件还有广告。有些延迟加载使用了低调的实现方式,其它的会导致回流和对用户的干扰。


网站的初衷很好,遗憾的是最后的结果不尽如人意。延迟加载更多的是伤害而不是提升整体的性能和可用性。尤其是三个延迟加载的导航不仅令人费解,还损害了性能。两个广告载入的方式也很烦人。


我给出的行动指南是:


  • 消除视觉混乱,关注核心内容和核心导航技术。

  • 尽可能少用延迟加载。要用就要避免造成回流,并且不要打断用户交互。

  • 将两个多余的导航部件合并成一个。区块和分类目录两个导航显得多余,因为前一个包含了后者。

  • 让跨站导航保持原样: 页面底部的一个简单链接就足够了。

  • 避免突然出现的广告。给主要的广告条留好占位空间。避免突然弹出广告条或者少用干扰性的插页式广告。



以上是关于我们的最佳实践正在扼杀移动 web 性能的主要内容,如果未能解决你的问题,请参考以下文章

同时从移动设备和 Web 刷新 JWT 令牌的最佳实践

转 Web程序优化的最佳实践:JavaScript和CSS篇

IOS 最佳 Web 视频编码实践 (FFMpeg)

架构最佳实践:Rails 和移动/Web 应用程序

ySQL性能优化的21个最佳实践 和 mysql使用索引

MySQL性能优化的21个最佳实践 和 mysql使用索引