renrenche-fe / awesome-articles

分享读过的好文章
MIT License
25 stars 1 forks source link

第十八周 2018-04-26 #18

Open sunhengzhe opened 6 years ago

sunhengzhe commented 6 years ago

本周因为要调研主站前端的重构方案,着重看了一下关于 Web 应用渲染模式的文章。 刚学前端的时候也会很疑惑,为什么 ajax 这么流行,我们还非得把前后端都混在一起,前后端分离不是一件很理所应当的事情么?事实上,前后端完全分离是有适用场景的,比如中后台系统。但对偏展示类的系统如电商网站等,SEO 和首屏渲染能力是需要重点考虑的,而这正是前后端分离的劣势。参考 Web 前后端分离的意义大吗?徐飞的回答。虽然是 3 年前的回答,但还是非常有启发性。

说到目前 Web 应用渲染的形式,大概也就是三种:客户端渲染(CSR)和服务端渲染(SSR),以及介于两者之间或者说结合两者的同构应用(isomorphic web apps)。

客户端渲染

客户端渲染是近些年流行的渲染模式,单页应用(SPA)就是一种典型的客户端渲染。服务端只提供简单的 HTML 骨架,页面主要内容全部使用 JS 生成,包括路由也是由前端控制。

优点

  1. 前端开发效率较高
  2. 成熟的技术方案
  3. 二次加载快

缺点

  1. SEO 不友好 页面内容是通过 js 生成的

    • 可以考虑专门做页面给搜索引擎
  2. 首屏性能 需要等待 js 加载完成才能 viewable and interactable

    • 代码分拆、按需加载
    • 优化体验:Skeleton Screen

服务端渲染

服务端渲染是长久以来流行的渲染模式,如 php 的 smarty、node 的 ejs 等。DOM 结构由服务端提供,JS 只负责处理交互。

缺点

  1. 第一字节时间(TTFB)速度比 CSR 更慢 需要耗费时间生成 HTML 与必要数据

  2. 服务器数据吞吐量要远低于 CSR

优点

  1. SEO
  2. 首屏渲染比 CSR 快
  3. 成熟的技术方案

同构应用

同构应用结合了 CSR 和 SSR,特点是同一份代码能够在客户端和服务端执行。老实讲前面这句话几乎在所有文章里都写了,但很少有文章会具体讲实现原理。一般来说,我们讨论同构应用,目前考虑的都是 react / vue + nodejs,因为同构应用的核心在于 虚拟 DOM。以 react 举例,当虚拟 DOM 应用于 web 端,就成为了 react,应用于 APP,就有了 react-native,应用于服务端,就有了同构应用。参考 Webpack实战-构建同构应用going-isomorphic-with-react

当请求到达服务端,服务端会计算虚拟 DOM,并生成 HTML 文本吐到前端,因为是同样的 DOM 结构,前端继续使用 react 进行后续的操作。参考 React Redux Sever Rendering(Isomorphic JavaScript)入門

由于同构需要引入 node 中间层,所以会有一定的运维风险和开发门槛。

关于 SSR 和 CSR 的比较,参考 前后端渲染之争聊一聊服务端渲染和客户端渲染

ShaofeiZi commented 6 years ago

个人感觉SSR和同构解决的方案差别不大都是去解决三个问题

  • 帮助网络爬虫(SEO)
  • 支持低带宽或低功耗设备
  • 快速加载首屏

同构应用的核心我认为是在Render而不是虚拟 DOM ,虚拟 DOM只是其中一个方法

还有一个问题是如何引用浏览器独有的原生对象,比如 window、document、navigator 或 location 目前大部分解决方案是写一个自己的抽象层,当在浏览器中运行时,就把它委托给浏览器 API,当在服务器中运行时,就提供一个符合要求的代用实现。这方面我感觉是个大坑,尤其是首屏幕显示后直接操作 而且由于没有鼠标或键盘事件,所以同构的应用也不能依赖于用户点击某个按钮来显示每个组件。 我认为同构应用应该仅仅根据客户端过来的请求决定要渲染的内容。 把应用做成可路由的。

由于服务端渲染页面的用户只能点击链接,所以应该尽快让它切换到真正的客户端应用,以提供正常的交互体验。如何去加载。也是个坑。

还有HTTP2之后模块如何分包。。

附上之前做的angular的SSR node版本 https://github.com/ShaofeiZi/angulrUniversal .netcore版本 https://github.com/ShaofeiZi/dotnetng2