【编者按】本文作者为 Mathias Schäfer,旨在回顾在客户端大量使用JavaScript 的最佳 Web应用实践。文章系国内 ITOM 管理平台 OneAPM 编译呈现。
对笔者来说,JavaScript 社区似乎已经陷入了一个时间扭曲隧道。我们现在进行的关于 JavaScript驱动(JavaScript-driven) Web 应用的讨论与2006年“Ajax”出现以及2012年JavaScript“单页应用”流行起来时的讨论如出一辙。只要我们站在巨人的肩膀上努力改进已有的最佳应用,那么,继续这样的讨论就是有意义的。
最近,Stefan Tilkov大放厥词,写了一遍名为“为什么我憎恨单页应用”的文章。文中提出了针对 JavaScript 网络应用的大胆断言和概括性表述。作为一个对渐进式增强兴趣强烈的人,看到这篇关于渐进式增强的粗劣分析,笔者感到很失望。
##多一些JavaScript Web应用,少一些单页应用。 首先,笔者认为“单页应用”是一个由来已久的错误概念,最终招来了对该概念的批评。笔者个人使用术语“JavaScript网络应用”来描述在客户端延伸使用JavaScript的网络应用,就像典型地使用Ember,React和Angular打造的应用一样。在上一篇贴文中,笔者写了一个简短的“单页应用”定义,但是其实应该使用“JavaScript网络应用”这一术语:
一个“JavaScript网络应用”指的是一个拥有复杂接口来提供高水平交互性的网站。交互性的很大部分都通过客户端的JavaScript实现,而且一些交互只能通过JavaScript实现。
有时候,HTML 需要在客户端进行渲染 ,但是并非必须。实际上,所有HTML代码或者至少其初始结构都需在服务器端渲染。
此类应用能避免用户每次输入后都进行服务器往返,而是让HTTP服务器在后台发出请求来发布动作或是载入新数据。
##传承最佳应用实践 2003年,Pamela Fox的一次综合性讲话描述了一个网络应用从用户和开发者角度来说必须满足的要求。该讲话基本确立了大量使用JavaScript的网络应用的最佳实践。
今天,大型的JavaScript框架拥抱的便是这些最佳实践。我们在2006年和2012年遇到的大多数问题已经在今天得到了解决。我们能够开发出在浏览器端动态呈现且快速可及的网站。使用渐进式增强(progressive enhancement),我们能够开发出健壮的JavaScript网络应用,保证其可用性 。
JavaScript网络应用并无特别之处,它们也仅仅是万维网中的一些超文本节点。因此和传统的网站一样需要建造在URLs上,故而连接和书签功能都一样。实际上,该问题早在2010到2012年间就得到了解决,那时浏览器和库已经支持HTML5 history API。
##更好的JavaScript网络应用 毫无意外,一些JavaScript网络应用并没有遵循这些最佳应用实践。网络协议栈中的任意一项技术可以说都是如此,如HTML或服务器端编程语言。我们要搞明白为什么一些网站不遵循最佳应用实践。
是因为这个概念使其难以应用鲁棒性原则吗?那么,让我们改进最佳应用实践,改善指南、库和工具。面对表现不佳的JavaScript网络应用,解决措施并不是完全摈弃,而是创建更好的应用。
##为什么我们要再次开发JavaScript Web应用? 十年前,网络创造者尝试弄明白本地应用的用户交互如何工作及其能提供哪些益处。为了效仿桌面应用的“丰富性和响应性”,它们将一些特定的已有模式应用于网络。
今天,我们需要回顾克服服务器往返和整页刷新的用户交互所具备的优势。我们只能通过已有的前端技术来提升用户体验。因此,我们需要确定能够且应该在客户端JavaScript改善的交互。
JavaScript是在浏览器中开发良好交互性的最佳技术。然而,对于客户端JavaScript开发者来说,最为重要的技能是决定什么时候不使用客户端JavaScript来解决问题。在协议栈中解决问题总是更加鲁棒。
从渐进式增强的角度来看,化解传统服务器端应用和JavaScript网络应用之间肤浅的二分法很有必要。从传统服务器端应用到依赖JavaScript应用的转变需要做到无缝。我们需要找到开发高架构同时又不失去低构架优势的方法。“通用JavaScript” 框架就是这样一个充满希望的方法。
##Web 应用架构 笔者想评价一下Stefan Tilkov关于网络应用构架的设定:
“在这个架构方法中(一个传统的非JavaScript网络应用),很明显,实际的业务逻辑责任完全依赖于服务器。……业务逻辑不属于客户,除非你愿意不厌其烦地处理每种你所支持(你不仅需要在服务器端维护处理,还请记住,你永远不能信任客户)客户的繁琐逻辑。”
这话并没有错,但是JavaScript网络应用自身并没有复制业务逻辑。
业务逻辑是建立在数据之上的一系列高水平操作。例如创建、阅读、更新和删除记录(CRUD),更新记录之间的关系,查找、转换或是合并记录以满足某个特殊的请求。
通常,业务逻辑存在于服务器代码中。数据最终在服务器中进行处理,因而数据应该是一致的,你也无法轻易篡改这里的代码和数据存储。所有的身份验证、认证以及安全检查都在此处进行。
一般来说,这个服务器代码提供一个能由多个客户(如网络或本地客户)使用的HTTP REST接口(API),这些客户一般都含有接口逻辑。
##在服务器和客户之间共享逻辑 举个例子,输入验证是片灰色区域。为了一致性,API服务器拥有对认证的最终话语权。然而,就算只是简单的输入验证都能提高用户的体验。这能及时地给出反馈,而不用让用户等待服务器请求和用户接口的更新。
这就将我们引向了著名的逻辑共享问题。该问题存在于每个无需客户为每次用户操作进行服务器往返的客户端服务器端软件构架中。这个问题既不是JavaScript网络应用独有,也不会因为不使用客户端JavaScript就能避免。
与简单地禁止在客户端实现有用的逻辑相反,让我们从方便用户的角度来谈一谈分享特定逻辑。再次说明,该问题不仅涉及JavaScript网络应用,还与所有从架构上与API服务器分开的客户端有关。
其实,有很多实用的方法可用于实现客户与服务器之间的逻辑共享。在表格验证的例子中,我们可以用中立的、陈述性的格式如JSON或XML来描述规则。每个客户都有粘结代码(glue code)以便读取和应用针对特殊用户接口的规则。
##用客户端-服务器架构取代单一结构 Tilkov写道:
“SPA(单页应用)方案导致问题的一个绝佳例子就是并行工作。如果你有一个多人团队甚至是天理不容地拥有多个团队处理同一个SPA,你需要想出一个好办法来做支持这个项目。或者,你也可以让每个团队都开发他们自己的应用。每个应用都能由相同的组织(如果你愿意的话,这也可以适用于其他任何网络应用)在同一时间连接起来 —— 实际上,这依赖于网络的核心力量”
笔者没有在此看出问题。实际上,有更大的团队以及多个团队在为构建真实世界的JavaScript应用而努力。Tilkov似乎将JavaScript构架与一般的独石构架相混淆了。以笔者的经验来看,JavaScript网络应用是松散联系的REST服务的最佳搭档。
如果你有一个面向服务的构架,使用相同的API,不同的团队可以开发出各异的并行客户端。这些客户端是JavaScript网络应用、传统网络应用或是本地应用都没有关系。这些客户端可以使用URL或安卓上的Intents等机制相互连接。
##JavaScript应用的可及性 在JavaScript社区中,可及性这一议题一直以来都处于被忽视的状态,而且在更大的网络开发社区中继续遭到忽视。为了提供当今网络应用的可及性,我们需要有意义的批评和建议。这也是为什么笔者对下面这种直言感到失望:
“就可及性而言,在服务器端使用语义HTML提供了一个绝佳的便利支持。”
这话太具有误导性。在服务器端使用HTML并不会提高可及性或语义更加明显。不管是你在服务器端或是在浏览器中使用HTML,你都需要写出可及的语义标记。
其实,可及性在服务器端呈现与客户端呈现之间存在差异:在客户端呈现的鲁棒性相对较差,因为你对客户的控制非常有限。但是一旦HTML被解析至DOM,可及性就变得一样了。
在使用JavaScript来显示、隐藏、插入或改变内容时,对可及性有特殊的要求。几乎所有的JavaScript都会执行这些任务。如果每次内容发生变化时你没有刷新页面,就需要使用WAI-ARIA技术来引导用户。而一些特定的如标签(tab)和动态对话(modal dialog)控制需要特殊的ARIA标记和人工调节管理。
##有价值的JavaScript网络应用 关于Tilkov的文章,笔者最无法苟同的是他认为JavaScript网络应用没有用处:
“[我所知的单页应用]都十分肿胀且加载缓慢,即使它们需要展示的信息和提供的交互十分简单。[…]”
“在我所知道的几乎所有案例中,你们的[单页应用]对用户来说毫无益处,而实际上,还有很多浏览器特性值得拥抱。”
虽然,可能的确存在简单交互的JavaScript网络应用,但是仅通过寥寥几屏,你无法看出其中的复杂程度。
笔者每天接触的大多数具有成熟浏览器交互的网络应用是用JavaScript开发的,而且只能用JavaScript开发:Flickr、Youtube、Facebook、Twitter、GMail等等。很有可能,你每天去逛的网站也都是由JavaScript支持的。你可能还没有注意到这点,因为它们依照最佳实践“就行得通”。
这些网站给用户带来了极大的益处。最终,每个软件、每个信息系统都应该允许用户简单快速可及地执行任务。这应该引导你的构架决策。
通过否认JavaScript对用户体验做出的巨大贡献,Tilkov推崇了一个笔者认为相当落后的渐进式增强。渐进式增强应该拥抱技术进步并承认用户的利益,但同时保证使用的技术具备鲁棒性与兼容性。
##JavaScript网络应用“在网上” 正如Greg Babiars所说:“看到这些谈论细微技术差别、讨论用户体验,还声称某种方法能解决所有需求的贴文,我的心很累。”
JavaScript网络应用已经被证明用处颇大,不会消失不见。因此我们不要再羞辱JavaScript了。在前端工具栈中,JavaScript必不可少。为了用户的利益,我们需要讨论的是何时如何正确地使用它。
我们需要停止以“网络本来的样子”为由而排挤JavaScript。和其他的网站一样,JavaScript应用也“属于网络”。网络潜力巨大,而我们的工作才刚刚开始。
网络最初是作为“文件检索系统”而被发明的,我们需要感谢通用访问一类的理念。但同时,网络还是一个“应用交付系统”。让我们尽量地调和使用这两种方法,而不是忽略或排挤其中一个。
本文系 OneAPM 工程师编译呈现。OneAPM Browser Insight 是一个基于真实用户的 Web 前端性能监控平台,能够帮大家定位网站性能瓶颈,网站加速效果可视化;支持浏览器、微信、App 浏览 HTML 和 HTML5 页面。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客