为了简单明了地理解什么是单页面应用,我们先对比一下传统的网页应用。如图一所示在传统的web应用中:

  • 客户端向服务器发送http请求
  • 服务器获取请求并作出响应。这个过程具体是先由控制器(control)做出路由的分发,匹配到相应的数据服务(model)然后结合这个数据服务生成一个template即HTML文档,这个template就是control的执行结果
  • 服务器会将这个HTML文档(视图)返回给客户端
  • 客户端将HTML文档渲染到页面

                                                               图一                                                                               

单页应用不一定就是MV*,用原生JavaScript也可以做单页应用。单页应用的本质我理解是我们的一个页面就像一个客户端程序一样可以实现各种各样的复杂的交互,包括与用户的交互、与服务端的交互等等。从另一个角度看,单页应用也有一个与之前的web页面形成对比的性质。

单页应用的原理如图二所示,明显看到单页应用将原本存在于server的MVC搬到了client端。具体包括:

  • C:控制器中的路由分发,即在浏览器端直接响应浏览器地址的变化,分发到对应的路由,向用户呈现对应的界面。
  • V:以小块组件为功能元件,类似于传统网页中的 Ajax 组件,单页应用以小的组件为功能元件,在路由变化时,不再刷新整个页面,而是组合这些小的组件,替换变化的部分。
  • M:数据层前置,与 Ajax 组件一个明显的区别是,单页应用在浏览器端通常有一层实实在在的数据层,而服务端则退化成了完全的数据 API。浏览器端的数据层会封装服务端 API,供上层的视图层调用。

                                                                 图二

SPA所解决的问题

以上两种对求情的处理方式中,传统的处理方式中虽然后端应用了MVC模式,代码可维护性得到明显好转,架构层面让开发者懂得什么代码应该写在什么地方。但是这种项目架构还存在很多不足:

  • 传统的web应用对路由的处理方式简单粗暴,页面由 JSP、PHP 等工程师在服务端生成,浏览器负责展现。基本上是服务端给什么浏览器就展现什么,展现的控制在 Web Server 层。
  • 另外,由于浏览器端只是一个展现层,当页面功能有所变化的时,页面就刷新,这会导致资源的浪费,用户需要花费额外的时间等待页面刷新,用户体验不佳。

出了问题方要改正,SPA的出现真正解决了上述问题。

具体的解决方案:

       首先路由分为两种,前端路由与后端路由。Web 服务会接收到请求后,会先解析 URI 中的后端路径(即代表整个应用的父路径)并将后端路由映射到对应的处理逻辑,这部分的路由分发仅分发到应用级别,没有映射到具体页面。对于路径中剩下的的前端路由,web服务器选择忽略,这部分的前端路由分发就已经具体到应用下的特定页面了。 JavaScript 是可以通过 window.location.hash 读取到到前端路由的。

  • SPA将应用下的子路由的前端化,实现了同一应用下的子路由的分发权置于浏览器端。
  • 读取到路径加以解析之后就可以响应不同路径的逻辑处理。进一步匹配到具体的组件的替换,而不是刷新整个页面。
  • 前后端职责很清晰。前端工作在浏览器端,后端工作在服务端。前端可以本地开发。后端专注于业务逻辑的处理:提供初始的 HTML 、提供 API Server 让前端框架可以取得资料用于前端 template。前后端数据都需要通过AJAX同步、提交。

SPA的不足

  • 首屏加载时间长:在首屏中需要加载大量的静态资源
  • 全异步,对 SEO 不利。往往还需要服务端做同步渲染的降级方案。
  • 性能并非最佳,特别是移动互联网环境下。