“Web 是我能想到的最复杂的开发环境。” Douglas Crockford 很多 Web 设计师和开发人员都有这样的烦恼,怎样才能保证我们发布的内容和用户看到的内容是一致的?我们真的有必要这样吗?下面通过三个案例来向大家解开这个疑惑。 案例一:2011 年 2 月,Gawker 传媒对其旗下的 Lifehacker、Gizmodo、Jezebel 等网站进行了统一改版。在这些新网站上线之后不久,用户诧异地发现网站的内容变成一片空白了(图 1),全部内容都不翼而飞。这是怎么回事呢?原来这场事故和 JavaScript 有关,准确地说,是因为这些网站的 JavaScript 代码并没有生效[1]。 图 1 2011年,Lifehacker网站经历了一场JavaScript事故 原因是这样的:这些网站改版的时候,采用了 JavaScript 作为内容的生成机制。网站的 HTML 页面只是一个空容器,当页面加载的时候,内容会通过 JavaScript 拉取出来,去填充整个页面。有些人认为,异步加载内容的方式使网站更像一个在线应用,显得网站非常高大上。但是千算万算,没有料到在网站上线当天,因为 JavaScript 中一个未测试出的 bug,所有的网页都没有拉取出任何内容。虽然后台服务器一切运行正常,但是因为一个 JavaScript 的 bug,Gawker 传媒旗下的这些网站全部裸奔了。可想而知,这些网站当天的访问数据是多么难看,更不用提因此损失的广告收入了。 值得玩味的是,随后好几年,Gawker 传媒旗下网站的内容发布机制再也没有借助过 JavaScript。 案例二:2014 年 1 月的一天晚上,英国最大的互联网服务供应商之一 Sky Broadband 制造了一个大新闻。他们的域名过滤机制误将 code.jquery.com 视为了“恶意软件和网络钓鱼”网站[2],而 jQuery 的 CDN(内容分发网络)正是基于这个域名。如果你不明白这是怎样一个大新闻,我可以解释一下。jQuery 是世界上最流行且没有之一的 JavaScript 类库。在世界上最流行的 10000 个网站中,有四分之三都依赖 jQuery 来实现业务功能。如果 jQuery 的官方 CDN 失效,后果可想而知。 当 Sky Broadband 发现这个域名存在“安全风险”后,迅速采取响应机制,阻止了这个域名的访问。对于那些既使用 Sky Broadband 的服务,同时也通过 CDN 方式引用了 jQuery 的网站来说,他们用以加载内容、显示广告,或是实现交互的 jQuery 代码一下子全部陷入了瘫痪。 案例三:2014 年 9 月,科技博客网站 Ars Technica 爆料称,美国最大的宽带通信服务商 Comcast 通过 Wi-Fi 热点向广大第三方网站中注入广告信息[3]。这种手法属于典型的“中间人攻击”[4],是一种无视网络安全的黑客行为。安全专家 Dan Kaminsky 对此发表评论称:“作为网站的开发者,你写的代码和在用户浏览器中执行的代码很可能不是同一套。用户看到了跟你的网站毫无关系的内容,这些内容你甚至在你的控制之外。” 不止 Comcast,还有很多组织在做一样的事。如果你在酒店、机场等公共场所使用他们提供的免费 Wi-Fi,通常他们都会在你上网的时候在页面中注入各种各样的广告信息。 很多 Web 设计师和开发人员存在一个认识上的误区:即认为浏览器提供对 JavaScript 的支持是理所应当的,如果说 JavaScript 可能导致一些问题,也仅仅是因为 IE8 的性能不足所引起的。我在上面举了三个近两年发生的例子,这些例子都和 JavaScript 有关,但都和浏览器支持程度没什么关系。可是,针对上面例子中的故事,作为一个开发者能做什么呢?打个不太恰当的比喻,你可能需要做的,是要开发一个类似一代名车克莱斯勒“帝国” 1964 年版[5]那样坚不可摧的一个网站,无论攻击来自何方,我们有充分的预案应对。这样,我们就要考虑各种因素,从终端设备、浏览器、插件,到服务器、网络环境,甚至路由器,都必须加入我们需要跟踪排雷的监测范畴。这样,我们才能保证我们发布的内容和用户看到的内容是一致的。但是,我们真的有必要这么做么? 了解潜在的问题,避免日后踩坑技术变化如此之快,几乎每周都有新的 JavaScript 框架面世。而每种新的 JavaScript 实现方案都曾被从不同角度冠以“革命性变化”的美誉。诸如 Angular、Ember、Knockout 和 React 等框架淘汰了传统服务端和浏览器端的工作模式,即服务端产生内容,浏览器端提供页面间导航关系的工作模式。这些框架可以做到异步处理服务端的请求,采取按需加载的方式控制完整的用户体验流程,减少页面刷新次数,缩短页面加载时间。 只有一个问题:没有 JavaScript 的话,就什么也做不了。 当然,我的目的并不是鼓吹说:“大家不要使用 JavaScript 啦,洪水猛兽呀!”[6]相反,我认为 JavaScript 是一个非常棒的工具,只要使用得当,JavaScript 绝对是提升用户体验的利器。 了解 Web 的性质在 Web 早期的时候,任何一名“有操守”的软件开发人员都会对 JavaScript 嗤之以鼻。绝大多数观点认为:这哪算得上一门编程语言?HTML、CSS、JavaScript 这些东西不过是奇技淫巧。在传统程序员的印象里,只有 Java、Perl、C 这些语言才能登大雅之堂。至于 JavaScript,歪门邪道,不足学也。但是,随着 JavaScript 自身的进化,一些事情近年来似乎发生了改变。 2005 年左右,随着 AJAX 悄然兴起,一些开发者逐渐开始关注起 JavaScript 来。但是当时的 Web 环境对程序员来讲,依然不是一个合适的用武之地。直到若干年后,随着一些成熟的 JavaScript 框架诞生,以及这些框架承诺会将传统的开发模式迁移到 Web 上,新世界的大门仿佛开启了,开发者们蜂拥而至,在 Web 界刮起一阵阵旋风。这总的来说是件好事为了促进 Web 的发展,我们需要更多的人进入这个行业。但是,传统软件工程师在发布 Web 代码的时候,也带来了一些不好的习惯。 在传统的软件开发中,执行环境是一个经常被讨论的问题。但是在 Web 中,这类问题不存在这一点我将会在以后进行解释。如果我正在使用 Python、Rails 或 PHP 来编写一个服务端软件,我的执行环境一定会符合下面两个条件之一。
在传统软件开发产业中,开发者可以按照代码的需要,规定软件的运行环境,例如系统要求、硬盘空间要求、内存要求等。用户看到这些信息后,自然会根据自己的硬件和软件环境来判断,是否能够运行你的软件。如果运行环境不满足,他们就只能去寻找其他的替代方案。 在 Web 开发中,开发人员就不能再这么任性了。相较传统软件可以面向不同的操作系统进行定向开发,Web 是一个既统一又混乱的平台。虽然用户访问的是同一个 Web,但是他们所持设备之间的性能差异巨大,导致浏览效果各不相同。所以,尽管我非常想把 Web 的用户体验精确到像素级别,但是这种期待注定要落空。Web 的工作方式决定了我们不可能在所有的设备中呈现完全相同的设计,于是,我们只能拥抱这种差异性,给出具有 Web 特点的适应性设计方案。如果你是一名从传统软件开发刚刚转到 Web 开发的工程师,理解这一点并不容易,这很正常,就我自己来说,理解这一点也花费了很长时间。 对于一名 Web 工程师来说,你无法指定你的 JavaScript、HTML、CSS 在什么环境下被执行、被解释、被渲染。一切代码环境都由你的用户来决定。比方说,处理器速度、内存大小这些你都没办法要求用户的设备达到你心中的标准。用户使用的是什么设备和操作系统?使用什么浏览器?浏览器是什么版本?这些你也没办法预测。除此之外,用户还有权在浏览器中安装插件,更换浏览器的皮肤和主题,改变浏览器默认字体和背景颜色。除了用户,网络环境也会影响产品的用户体验。网速、流量以及运营商对内容的防火墙管制,都会或多或少对你的产品造成影响。你能做的,只是提供一个考虑到各种限制情况下的方案,发布出去,然后期待一切正常。 一个最基本的问题是,很多框架将 JavaScript 本身作为构建视图的工具使用。如果你能够保证用户使用的是最新的设备,且带宽稳定网速够快的话,这么做是没有问题的。如果你从未跳出行业思维,去观察真正的用户,你可能会认为他们的设备理所应当支持你的所有代码。当然,如果你开发的是一个服务企业内部的 Web App,你完全可以要求每个用户统一他们的系统和浏览器设置,以符合你的代码的运行要求。但是对于开放的 Web 来说,如果你希望互联网上的任何人都能访问你的网页,你就不能对任何一种技术抱以绝对的信任和依赖。 考虑用户访问网站的各种具体情况,平衡各种访问环境下网站的用户体验,然后审慎地使用 JavaScript 等技术这是一件值得思考的事情。既能看到技术能够带来的体验提升,同时也要明白,我们用到的技术未必在每个用户那里都能奏效,这也就是我们所说的渐进增强。 Web 的历史,某种意义上就是一部 JavaScript 的折腾史,甚至可以说是灾难史。但即便这样,也不意味着你不应该使用 JavaScript,或者 JavaScript 本身有什么原罪。抱着“不折腾,不成活”的精神,我们更应该开动脑筋,找到驯服 JavaScript 的方法。另外,JavaScript 只是解决问题的工具,问题的核心在于你的网页或产品需要让用户简单快速地获得他们需要的信息,完成他们的任务。如果本末倒置,将核心界面交给 JavaScript 来驱动,就算交互设计再精良,一旦用户的环境不支持 JavaScript,网页也就会瞬间陷入瘫痪。 什么情况下会“无 JavaScript”通常,我们在讨论“渐进增强”的时候,这个术语基本等同于“无 JavaScript”的意思。当然,渐进增强还有其他的内涵。在当今的 Web 环境下,无数用户的浏览器中运行着 JavaScript,大多数浏览器都提供 JavaScript 支持,几乎没有人会专门跑到浏览器设置页面,将 JavaScript 功能手动关闭。作为 Web 设计师,你当然可以,而且有责任使用 JavaScript 去构建精美而酷炫的网页体验。 既然几乎所有的 Web 环境都支持 JavaScript,有人就会问了,那么我们为什么要去担心“无 JavaScript”这种情况呢?我希望大家可以从我在开头举的那些案例中得到一些启发。如果那些案例还不足以说明问题,一定要我解释“无 JavaScript”到底是一种什么样的情况,那么我可以拿出一些数据出来:英国的政府数字服务机构(GDS)曾经做过一个实验,目的是为了发现有多少互联网用户是禁用 JavaScript 的。实验结果显示,禁用 JavaScript 的用户占了样本总量的 1.1%,即在 93 名网民中,有 1 个人禁用了 JavaScript[7]。这个比例放在亚马逊身上,就意味着每月有 175 万用户是在无 JavaScript 支持的情况下访问他们的网站的。175 万,多么庞大的数字[8],但这还不是重点。 首先,关于 GDS 所使用的实验方法在这里需要说明。这个实验所需的代码运行在一个大流量的页面中,访客范围来自全球各地。实验根据页面中图片渲染出来的数量来判断和收集用户的浏览器状态。具体来说,实验本身使用了三种不同的方式创建了三张图片。
当浏览器不支持 JavaScript 代码的时候, 根据上面的设置,预期结果是每个用户都能访问到两张图片:如果用户的浏览器不支持 JavaScript,用户访问到的是图片 1 和 2( 但是,GDS 没有预期到,实验结果中出现了第三类用户,这类用户只访问到了图片 1,另外两张图片都没有访问到。换句话说,他们的浏览器都应该是支持 JavaScript 的(因为noscript元素中的内容没有被暴露出来),但是他们并没有访问到通过 JavaScript 代码载入的图片。更让人感到诧异的是,第三类用户在整个样本中所占的比例(0.9%),这比那些因浏览器完全不支持 JavaScript 而看到两张图片的用户比例(0.2%)还要大。 是什么原因导致类似这样结果呢?可能有下列多种原因。
图 2 2012年,用户通过一台黑莓设备访问奥巴马的竞选网站。4.2MB的HTML、CSS和JavaScript导致该设备内存不足(http://perma.cc/K8YS-YHDV) 使用 JavaScript 构建核心用户体验的话,用户可能会遭遇到许许多多的潜在问题我并不是让你彻底和 JavaScript 说拜拜,我只是让你知道这么做会产生什么样的潜在风险。说实话,大多数用户很少被这些风险所影响,但是,我还是建议不要把所有的用户体验要素都寄托于 JavaScript 上。通过不同的技术方案去提供多样化的体验,可以把风险降到最低,同时可以兼容更多的设备,让更多的用户能够有效访问你的网站。我们需要朝最好的方向努力,但也要做最坏的打算。 保证最基础的用户体验在设计一个网站时,我们要首先考虑的是,如何可以在不依赖 JavaScript 代码的情况下完成主要的产品闭环。无论用户的浏览器支持 JavaScript 与否,最起码的注册、登录、购买等基本功能是必须要实现的。其实,这些功能利用最基础的 HTML 元素就可以完成,比方说,通过超链接实现页面间的跳转,使用标准表单完成和服务端的通信,等等。HTTP 协议是 Web 的基础,我们应该合理利用它,完成最基础的用户体验。 使用一些非原生控件去实现交互行为,比如表单的异步提交,将会增加更多额外的交互 JavaScript 代码。使用原生的超链接,默认的表单按钮和其他在 HTML 中提供的基础原生控件,会有效降低网站对交互 JavaScript 代码的依赖。无论用户通过何种网络环境和设备访问你的网站,这么做都能至少满足用户最核心的功能诉求。 当然,当你面对的是基于 MVC(即模型-视图-控制器)模式的框架(如Angular、Backbone、Ember等)所构建的单页面Web APP(即SPA,Single Page App)的时候,事情就要更复杂一些了。事实上,这种开发模式的普及令很多JavaScript开发者转变了思想,宣称渐进增强的思想必然要被淘汰就像 Ember 的创始人 Tom Dale 在 2013 年 11 月宣称的那样[10]。 “现今,JavaScript 已经可以被视为 Web 平台不可分割的一部分。担心浏览器不支持 JavaScript,就好像担心你要不要向后兼容 HTML3.2 和 CSS2 一样荒谬。一些技术已经事实上成为了 Web 平台的一部分,在 2013 年的今天,我们完全不需要为这种事情担忧。” 感谢 Node.js,JavaScript 如今已经越来越普遍地作为服务端语言来使用了。开发者们可以将代码在后台处理好,然后再发送到浏览器端。这种被 Nodejitsu 称为同构 JavaScript 的技术[11],允许服务端用传统的方式响应页面请求,并返回传统的 HTML、CSS 和 JavaScript 文件(图 3)。这些 HTML 页面会包含指向其他页面的链接,以及和服务器通信的普通表单。如果条件成熟的话,所谓最基础的用户体验就可以考虑利用 JavaScript 了,然后单页面 WebAPP 就会大行其道。这就成了渐进增强的一个奇妙的例子:在技术成熟之后,之前我们坚持的以无 JavaScript 作为最基础的用户体验的技术基准,将会被单页面 WebAPP 所取代。 图 3 该图解释了同构JavaScript的工作原理。图片源自Airbnb,笔者有所修改
2012 年,Twitter 成为了第一个尝试单页面 WebAPP 的大型网站(尽管并未在服务端使用JavaScript)。Twitter 发现此举让网站的用户体验变得更为稳定了,另外还提升了网站的访问速度。在使用MVC框架后,网站的渲染时间降低到了原来的五分之一[12]。一年后,Airbnb 应用同构 JavaScript 方法重构了他们的网站,提升了页面性能和网站的 SEO 效率[13]。 在随后的几年里,越来越多的网站进行了类似的优化,而更多的 MVC 框架也逐渐为人们所知。Tom Dale 顺势而为,也推出了新的 Ember FastBoot[14]。 “比起在客户端渲染页面在服务器渲染页面往往更加可靠。对于那些并未使用性能优异的最新设备的用户来说,服务端的渲染尤为重要。因为当用户点击一个链接的时候,他们能够立即看到你准备好的内容。” 这些话我完全同意。在客户端执行 JavaScript 从来都不是特别靠谱。所以,我们才更需要在一开始设计一个没有 JavaScript 支持的最基础的用户体验,并通过服务端发布出去。就算在单页面 WebAPP 和客户端 MVC 框架的时代,保持渐进增强思想依然是很有意义的。
[1] http://perma.cc/B7KR-HWLM [2] http://perma.cc/KRX9-V82T [3] http://perma.cc/E53Y-LL39 [4] http://perma.cc/RB97-MENZ [5] 作为一个资深汽车爱好者,我毫不怀疑 1964 年版的克莱斯勒“帝国”是一代传奇。当年坊间常举办一些荷尔蒙过剩的汽车运动,大家互相开着各种车撞来撞去。在所有车辆接连报废后,最后横冲直撞毫发无损的永远是一辆 1964 年版克莱斯勒“帝国”。因为这车坚不可摧,后来它被永远禁止参加撞车比赛。 [6] 如果持这种观点,本文就不会有这么长。 [7] 皮尤研究中心(Pew Research)最新的研究报告显示,JavaScript 不生效的网民数量占样本总量的比例达到了让人咋舌的 15%。这份报告指出,Web 上 JavaScript 驱动的工具型网站降低了调查的数据质量:http://perma.cc/W7YK-MR3K。 [8] 据我了解的最新数据,亚马逊月独立访客为 1.75 亿。数据来源:http://perma.cc/ELV4-UH9Q。 [9] Stuart Langridge把这些JavaScript缺失所导致的情况制作成了一个漂亮的图表,你可以把它打印下来贴在墙上时刻提醒自己。 [10] http://perma.cc/DP6Q-FAZ5 [11] http://perma.cc/GHW9-SNKT [12] http://perma.cc/AE92-4UTF [13] http://perma.cc/HL7R-9ZJ5 [14] http://perma.cc/27DP-NJ99 (本文节选自Aaron Gustafson作品《渐进增强跨平台用户体验设计》)
(点击图片,查看全书)
|