1.2 从静态页面到Ajax、再到全功能Web应用
从20世纪90年代中期引入万维网(WWW或W3),到21世纪00年代中期Ajax出现之前,大多数的网站本质上是静态网站。服务器端通过一个HTTP响应来应答所有HTTP页面请求,该响应包含了显示一个完整页面所需的全部HTML、CSS和JavaScript代码,如图1-3左半部分所示。
虽然许多网站仍然如图1-3左半部分所示那样,依赖于整页刷新的方式,但越来越多的开发者都在创建动态内容。今天,用户希望在体验网站时能够做到页面不要刷新。
1.2.1 异步Web应用的兴起
随着异步调用功能的引入,其提供了为每个响应发送特定内容的能力。客户端有专门接受这个响应的JavaScript代码,并会替换网站中所有相关的HTML元素内容,如图1-3右半部分所示。这看起来很好,但这种方式存在一个很大的问题。
在服务器端实现一个服务是很容易的事情:给出一个元素类型,呈现元素的新内容,并以原子级的完整方式返回给浏览器。如果这就是富Web应用用户所需,那就没那么多麻烦了。但问题是用户极少一次只更新一个元素。
比如,当你浏览在线商店的时候,会搜索商品项并将其添加到个人的购物车中。但添加一项商品到购物车时,你理所当然希望商品数量以及购物车商品总金额也相应更新。这样你才知道购物车里的商品总数以及总金额到底有多少。
由于服务器端在每个Ajax响应中应该明确包含哪些元素的规则很难定义,大多数服务器端框架都直接发送整个页面给客户端。同时,客户端知道应该用哪个元素替换/互换对应的HTML元素。
如你猜到的,这种方式效率很低,其意味着增加了大量客户端发送到服务器端的HTTP请求,而这正是Ember.js的用武之地。作为一名开发者,你或许理解图1-3所示模型的问题所在,服务器端为页面上单个元素返回更新过的标记,而要更新多个元素,你就需要采取以下的某种方式。
- 要求浏览器为每个要更新的元素触发额外的Ajax请求。
- 时刻记住——同时在客户端和服务器端——针对用户在应用中执行的每个操作,都要相应更新元素。
第一种方式增加了HTTP调用服务器端的次数;第二种方式需要你在客户端和服务器端同时管理用户状态。因此,这大大增加了HTTP请求的次数,导致服务器端负担加重,但又无法减少服务器端处理每个请求的工作量。别误解了,这种模型下,通过判断元素标识符来替代元素,以及挑选出服务器端所返回完整标记中的特定元素,是可以支持局部页面更新的。但如你所想,这种模式同时浪费了服务器端和客户端的资源。图1-4说明了这种结构。
理想情况下,我们希望只在初始时服务器端将完整应用一次性传送给客户端。当整个应用加载后,客户端只需提交数据请求。伴随这种想法让我们进入Ember.js使用的模型。
1.2.2 Ember.js模型
以往,大多数网站忽视在服务器端与客户端间传递标记,而更关注数据传递。这正是Ember.js擅长的领域,如图1-5所示。
在图1-5中,用户在初次请求发出后一次性接收完整的网站。这将导致两件事情发生:增加初次加载的时间,但也意味着随后每次用户操作时性能得到提升。
实际上,图1-5所示的模型与可追溯到20世纪70年代的传统客户端/服务器端模型类似,但有两个重要的区别:初始请求充当客户端应用程序高度可行且可定制的分发渠道,同时确保所有客户端遵循一套通用的 Web 标准(HTML、CSS、JavaScript和其他)。
随着客户端/服务器端模型提出,涉及用户交互的业务逻辑、GUI(图形用户界面),以及执行逻辑已从服务器端转移到了客户端来处理。对特定部署而言这种转移会带来一定的安全问题,但在通常情况下,只要服务器端控制着所请求数据的访问权,安全事宜就可以委托给所属的服务器。随着客户端和服务器端职责的清晰分离,客户端和服务器端就可以各司其职——分别关注用户界面和数据处理。
现在你理解了通过Ember.js创建的Web应用程序的类型,接下来将进入到Ember.js内部。