前端架构经验谈之三

多页面应用

传统多页面是由后端控制一个 url 对应一个 html 文件,页面之间的跳转需要根据后端给出的 url 跳转到新的 html 上。比如:

1
2
3
http://www.example.com/page1 -> path/to/page1.html
http://www.example.com/page2 -> path/to/page2.html
http://www.example.com/page3 -> path/to/page3.html

多数情况下,这种方式都是没问题的,但对一些业务逻辑相似,重前端的应用就不是很友好了,比如系统管理应用。

  • 页面之间的跳转需要重新加载资源,这样就不能很好的重用公共文件,也使体验不顺畅;
  • 不能动态更新页面的路由,因为已经被后端定义好了,更改比较麻烦;
  • 对于 UI 类似,业务逻辑类似的页面,不能够很好的共用代码;
  • 对后端来说,每添加一个页面,都需要加一个路由,也是很麻烦的。

单页面应用

单页面应用(single page application),就是只有一个页面的应用,页面的刷新和内部子页面的跳转完全由 js 来控制。一般单页面应用都有以下几个特点:

  • 本地路由,由 js 定义路由、根据路由渲染页面、控制页面的跳转,这是单页面应用最基本的特点;
  • 所有文件只会加载一次,最大限度重用文件,并且极大提升加载速度,让 web app 有了 native app 的流畅体验;
  • 按需加载:单页面应用一般都会加上这个特性。
    这样一来,整个应用便只有一个 html 文件,路由由前端控制(有时候需要后端配合),前端对应用的控制就变得游刃有余了。

路由

一般来说,单页面应用的路由从表现形式上来说分为两种:Hash Router 与 Browser Router

Hash Router(哈希路由)

通过 location hash 定义路由。

1
2
3
4
5
6
7
http://www.example.com -> path/to/main.html

http://www.example.com -> 主页面
http://www.example.com/#/ -> 主页面
http://www.example.com/#/page1 -> page1 页面
http://www.example.com/#/page2 -> page2 页面
http://www.example.com/#/page3 -> page3 页面

这样做的好处是后端只需要给一个 url 就可以了,因为路由完全是由前端实现的。

Browser Router(浏览器路由)

通过浏览器链接定义路由。这个时候,每次路由就都像正常的浏览器链接跳转一样。

这种路由需要后端配合,就是把所有需要路由的 url 都指定同一个 html 文件,由前端来根据 url 判断怎样渲染页面。

1
2
3
http://www.example.com/page1 -> path/to/main.html
http://www.example.com/page2 -> path/to/main.html
http://www.example.com/page3 -> path/to/main.html

这样做的好处是对搜索引擎友好,对浏览器的表现就像正常的 url 一样。

什么时候需要“服务器端渲染或 node 中间层

在前后端分离之后,后端语言的模板功能被弱化,整个页面的渲染基本上都由前端 js 动态渲染,但这样对于一些应用来说是有缺陷的。比如需要 SEO 的,需要打开页面不用等待就能看到页面的,这尤其对于电商类应用是必需的。解决这个问题有两个思路:

  • 服务器端渲染(SSR):就是服务器端和前端共用同一个应用,然后通过构建工具及配置,确定哪些组件需要在服务器端渲染,哪些组件需要在客户端渲染;
  • node 中间层:保留服务器端模板渲染的功能,但是由 node 程序来代替以往的后端语言进行模板渲染(毕竟前端更懂前端),后端语言与 node 程序只做数据交互。

服务器端渲染

服务器端渲染,由框架与构建工具配合,并依据一定的项目结构和编码方式,共同运行。现有比较好解决方案:

  • next.js: 服务器端渲染 react 组件,用法和介绍建议查看 用Next.js快速上手React服务器渲染。
  • nuxt.js: 服务器端渲染 vue 组件,用法和介绍建议查看 https://zh.nuxtjs.org/。

对于 react, gatsby 也是一个不错的解决方案。服务器端渲染,社区还在不停的探索中,期待未来的新体验。

node 中间层

alt text

为什么选择node做中间层?

  • 前端熟悉的语言,學習成本低
  • 都是JS,可以前后端复用
  • 体质适合:事件驱动、非阻塞I/O
  • 适合IO密集型业务
  • 执行速度也不差

alt text

案例分析:淘宝首页优化
需求:静态资料展示,方便运营管理,更好的承载密集且庞大的流量
解决方案:页面缓存与定时刷新,返回缓存资料,NodeJS产出静态页面到CDN,定时刷新

alt text

案例分析:淘宝详情页优化
需求:单日四亿PV,页面数据来自各个不同接口,为了不影响体验,先产生页面框架后,在发起多个异步请求取数据更新页面,这些多出来的请求带来的影响不小,尤其在无线端
解决方案:在NodeJS端使用 Bigpiper 技术,合并请求,降低负担,分批输出,不影响体验

选择node做中间层好处多多,其中包括

  • 接口性能优化,拆分大接口为独立小接口,并发请求,串行 => 并行,大幅缩短请求时间
  • 部属优化,一台NodeJS对多台JAVA服务器,合理的分配服务器带来最大的产出
  • 页面渲染优化(前后端共享模版,首屏服务器渲染,次屏浏览器渲染,局部刷新浏览器渲染)
  • 单页面应用优化(前后端共享路由与模版,前端换页,浏览器端渲染,直接输入网址,服务器渲染,SEO问题迎刃而解)
  • 可靠性优化(单元测试,页面测试,回归测试,持续集成)
  • 更多的改造性:接口服务化,代码模块化,功能组件化