【编者按】本文作者为 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 官方博客

原文地址:http://molily.de/javascript-web-apps/

JavaScript Web 应用最佳实践分析的更多相关文章

  1. javascript编程的最佳实践推荐

    推荐的javascript编程的最佳实践,摘要记录在这里: 可维护的代码保证代码的性能部署代码 1 可维护的代码1.1什么是维护的代码:可理解性——其他人可以接手代码并理解它的意图和一般途径,而无需原 ...

  2. (译) 《Javascript 24条最佳实践》

    (摘录) <Javascript 24条最佳实践> 自己一直偏向于实用主义,不是学院派,不是学究派,只讲究把东西能够很好的做出来,但经过一段时间的开发工作当自己总结出来一些东西时,觉得挺有 ...

  3. ASP.NET Core Web API 最佳实践指南

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 介绍 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难 ...

  4. 【转】超实用的JavaScript技巧及最佳实践

    众所周知,JavaScript是一门非常流行的编程语言,开发者用它不仅可以开发出炫丽的Web程序,还可以用它来开发一些移动应用程序(如PhoneGap或Appcelerator),它还有一些服务端实现 ...

  5. 超实用的JavaScript技巧及最佳实践

    众所周知,JavaScript是一门非常流行的编程语言,开发者用它不仅可以开发出炫丽的Web程序,还可以用它来开发一些移动应用程序(如PhoneGap或Appcelerator),它还有一些服务端实现 ...

  6. 超实用的JavaScript技巧及最佳实践(上)

    在这篇文章中,作者将会向大家分享JavaScript开发的小技巧.最佳实践等非常实用的内容,不管你是前端开发者还是服务端开发者,都应该来看看这些小技巧,它们绝对会让你受益的. 文中所提供的代码片段都已 ...

  7. Web 前端最佳实践

    Web 最佳实践   前端   选择器 尽量使用ID选择器 基于Id的选择器:先使用ID选择器定位,然后再使用find方法精确查找   // Fast: $( "#container div ...

  8. 8102 年的现代 Web 开发最佳实践(笑)

    简评:8102 年了,现在 web 开发的最佳实践是什么,让本文来告诉你.原文只提到一部分,可以查看 reddit 上对此文的评论查看补充的最佳实践 https://old.reddit.com/r/ ...

  9. [转]ASP.NET Core Web API 最佳实践指南

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 转自 介绍# 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但 ...

随机推荐

  1. 详解Python中的join()函数的用法

    函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下:     join():    连接字符串数组.将字符串.元组.列表中的元素以指定的 ...

  2. B+树 -- Java实现

    一.B+树定义 B+树定义:关键字个数比孩子结点个数小1的树. 除此之外B+树还有以下的要求: B+树包含2种类型的结点:内部结点(也称索引结点)和叶子结点.根结点本身即可以是内部结点,也可以是叶子结 ...

  3. Java保存文本文件

    String requestData = "something you want to save"; String saveFilePath = "C:\\Users\\ ...

  4. 面试题22:有序数组生成不同结构BST

    对于一个含有n个数的有序数组1~N,能够产生多少种不同结果的二叉搜素树BST? 如何生成这些不同结构的BST? 有序数组如何生成平衡二叉搜索树? class Solution { public: in ...

  5. C++中模板与泛型编程

    目录 定义一个通用模板 模板特化和偏特化 模板实例化与匹配 可变参数模板 泛型编程是指独立与任何类型的方式编写代码.泛型编程和面向对象编程,都依赖与某种形式的多态.面向对象编程的多态性在运行时应用于存 ...

  6. 笔记五:python字符串

    一:学习内容 字符串类型 字符串类型判断 字符串类型互转 字符串小练习 二:字符串类型 1. basestring 在python中和字符串相关的数据类型为:str和unicode,他们都是bases ...

  7. Rails中activeAdmin的使用

    一.开始ActiveAdmin Active Admin是一个发布在RAILS3中使用的Gem. 1.我们为了快速开始我们对Active Admin的了解,我们首先安装它: 在你GemFile中添加g ...

  8. Linux下svn服务器搭建

    初次在linux上搭建svn服务器,本来以为很繁琐,其实很简单,主要分为以下几个步骤: 1.  首先安装subversion,命令:yum install subversion 2.  创建svn仓库 ...

  9. JPA之@Entity、@Table、@Column、@Id

    Java Persistence API定义了一种定义,可以将常规的普通Java对象(有时被称作POJO)映射到数据库.这些普通Java对象被称作Entity Bean.除了是用Java Persis ...

  10. JS数组sort比较函数

    转载:http://www.cnblogs.com/ljchow/archive/2010/06/30/1768683.html 我们知道,数组的sort方法可以对数组元素进行排序,默认是按ASCII ...