从 Next.js 到 Angular Universal

Tags
Web Dev
Angular
React
Published
December 16, 2021
Author
HJS
你现在看到的这个博客是 fork nobelium 项目改造的,这是一个基于 Next.js 搭建的项目,在我阅读 Next.js 文档到 Pre-rendering 章节时产生了一些关于前端预渲染相关的灵感,用这篇博客记录一下。
 

Next.js Pre-rendering

Next.js 有两种形式的预渲染,SSRSSG,如果不熟悉请查阅相关文档;在 Next.js 中如果存在异步请求,使用预渲染需要 2 个条件:
  1. 只能在 "Page" 组件中做预渲染
  1. 暴露 getStaticProps 等预取数据的方法
如果请求逻辑应内聚在深层级组件,数据就必须从 Page 级组件透传。这是为了限制开发者仅能在 Page 组件做数据预取,毕竟 Next.js 如果静态分析整个组件树难度会大得多。从 DX 角度看还有优化空间:
  • 开发者还需要额外维护服务端预取数据的逻辑
  • 如果可以更希望将预取数据逻辑和所关联的组件写在一起
 

Angular Universal

Angular Universal 的预渲染完全做到了零侵入,基本不需要在 angular 应用上做任何限制,而这都取决于完全不同于 Next.js 的设计。
Angular 使用 Zone.js Patch 了大多数 WebNode 中的异步 API ,它会等待所有"宏"任务结束后才去渲染生成 HTML 字符串,因此它不需要使用"数据预取"这种方式;此外还注入可一些例如 Document 的通用抽象,基本做到零侵入。
但如果等待所有异步 API ,意味着 setTimeout 同样会被等待,渲染出来的 HTML 并不是真正的”首屏“内容,这会导致Hydrate 失败而重新渲染页面。
 

总结

就预渲染这个角度看,Angular 这种无侵入的方式更让我欣赏,基于依赖注入 + Patch 方向的想象空间很大;但目前为止 Angular UniversalDX 也有一些问题:
  1. 约定太少,以致于类似预取数据后服务端内联,客户端加载逻辑要开发者自己维护
  1. 官方文档有待提高,类似 TransferState 这类关键的预渲染 API 竟然只在 Blog 中才有提到
可以看出在预渲染方面暂时不是 Angular 的主要方向,因此有该需求的网站建议用 Next.js 😅
 

拓展阅读