SPA 优点,我认为更多是在软件工程方面,SPA 形式可以做到前后端彻底分离,只要制定好 API 规范,那么前后端就可以独立开发,并且一套 API 可以同时供多个「端」使用。同时,SPA 倾向于将更多的业务逻辑移动到前端实现。此外,前端有了更好的模块化工具,可复用组件以 js 库的形式进行复用,更容易维护(相比 MPA,通常复用是由模板系统提供的能力)。此外,利用 webpack 的 loader 机制,可以实现更集约化的模块,例如 Vue 的 Single File Component,将相关的 html、css、js 代码集中在一起管理。

SPA 的缺点,我觉得有几方面:

  • 在刷新网页(或从其他地方跳转过来)时用户体验不佳。由于 SPA 所有的数据都需要通过 API 获取,对于内容型网页,首次打开时,需要先加载 SPA 的代码,启动 SPA 应用,然后再通过 API 获取数据,有时候可能需要获取多种数据,需要多次 API 请求,用户体验并不是很好。(虽然可以用服务端渲染 SSR 技术,但该技术带来的额外成本并不低,包括运维成本,也包括一些代码上的妥协)
  • 全局状态管理,对开发者要求很高。例如现在 vue-app 的启动逻辑,我相信大多数开发者都无法做到了如指掌。例如登录页面会有许多入口,应用内跳转、用户直接打开、微信授权后回跳等等,有些途径过来不需要请求 GetUserinfo,有些途径过来需要,像微信授权回跳这种,不少逻辑原本可以直接在后端做的,也不得不在前端实现一遍。这些因素提高了对前端开发者能力的要求。
  • 单页应用虽然将一些逻辑移动到了前端,但后端的开发成本并没有降低。
  • 对 SEO 不友好。这个其实应该 blame 百度,而不是单页应用技术本身。目前主流搜索引擎应该都对 SPA 很友好,唯独百度不行。

MPA 优点,上述 SPA 的缺点都对应 MPA 的优点,这里不再复述一遍。对于“澄清”一些大家可能会觉得是 MPA 缺点的方面:

  • 许多开发者可能对于页面内的交互操作的印象都是 jQuery,不支持数据双向绑定(或者很麻烦),代码笨重。但实际上单页应用也可以使用Vue、React等工具来“接管”页面内的一些组件,甚至整个页面。
  • 难以搭配 webpack 工具链使用。在网上这方面的 best practice 确实很少。此外,对于哪些东西由 MPA 模板引擎渲染、哪些由 js framework 渲染,这两者如何结合,对于这个边界问题,许多开发者可能难以把握。

MPA 缺点,同样,与 SPA 的优点对应。前后端代码没有很好的解耦,前端开发者需要有一定的后端代码阅读和开发能力,在分工开发时如何协调 commit 之间的冲突也是一个比较麻烦的事。

那么,什么情况下适用 SPA、什么情况下适用 MPA?以下是一些“简单粗暴”的建议:

  • 要考虑 SEO 时,用 MPA。我认为 MPA 的附加成本是低于 SSR 的。
  • 对于入口比较多的页面(比如登录页面、扫码进入的页面等),使用 MPA。必要时 MPA 和 SPA 可以混合使用,即部分页面使用 MPA,其他页面使用 SPA。
  • 类似 网页 形式的应用,使用 SPA。
  • 移动应用(不含小程序),鼓励使用 MPA。