Skip to content

Latest commit

 

History

History
98 lines (68 loc) · 5.33 KB

rendering-pattern.md

File metadata and controls

98 lines (68 loc) · 5.33 KB

PPR渲染模式总结

更新于:23.12.08

回想一下传统的SSG页面中,如何加载动态内容,比如商品页加最近30天购买数,文章页加评论信息,信息流加推荐。

  • 传统的做法: 静态部分渲染出来,比如宝贝描述、文章内容、推流内容等,然后在客户端异步获取动态内容

而PPR则是:

  • 将这一部分挪到了服务器上,将静态部分渲染出来
  • 然后动态的内容通过Suspense包裹,NextJS将会通过占位的方式优先进行渲染
  • 随后通过推流替换占位内容

目前有5种模式渲染,具体根据情况灵活运用,没有最好或最合适

以下是内部交流截图

2331701967035_ pic

重新总结

更新于:23.11.07

  • 总结:NextJS默认以静态模式,或试图最大化静态模式进行渲染
  • 区别
    • 静态渲染:是指在构建时或请求前预先缓存,在下次请求优先读取缓存作为响应
    • 动态渲染:需要经过服务器进行计算渲染,给出响应结果
  • 3种动态渲染行为:
  • 关于服务端fetch [总结]
    • fetch和视图(component tree)是两条单独的缓存路线
    • fetch默认也是在构建时静态缓存,一旦缓存之后所有请求都直接从缓存中读取给出响应
    • 除非声明fetch动态渲染:no-storerevalidate
  • 综上所述,如何判断当前路由段是动态还是静态:
    • 看url对应的目录、看路由段声明、看动态函数、看fetch是否有额外声明
    • 如果都没有,那么就是静态
    • 再回想下自己的业务页面所需哪些功能,采用哪种渲染是不是清晰多了?
  • 通过以上总结再来看NextJS的几个渲染模式
    • SSG:静态渲染,包括有generateStaticParams和静态的single page
    • SSR:含动态路由、方法、声明、动态fetch
    • ISR:带有时间间隔的缓存SSR
    • CSR:hydrate后在client side进行interactive部分
    • PPR:混合动态和静态渲染部分

NextJS 4个模式的关系

NextJS 4个模式的关系

  • NextJS默认所有page都是SSG,需要通过调用动态函数cookiesheaders,或者通过声明revalidatedynamic转换为SSR
  • 可以通过generateStaticParams去声明SSG的渲染范围
  • 无论SSG还是SSR,服务端所有的fetch都将在build前以SSG方式完成加载,build之后不再请求,除非将fetch采用cache: 'no-store模式(具体看上述fetch总结)
  • no-store模式下,通过revalidate实现ISR
  • SSR + use client实现CSRSSGbuild后可采用CSR方式对边缘计算做交互

SSG的坑点:

  • 随着NextJS 14增加的PPR模式,这个坑点将可能不复存在 [查看ppr模式]
SSG不能动态渲染的问题请通过PPR解决

一旦通过generateStaticParams去声明SSG渲染,无论是在page中,还是在page上方的布局中,请不要在服务端去调用cookiesheaders这样的动态函数,否则会报错[NEXT-1181] DynamicServerError: Dynamic server usage: cookies,见issue:vercel/next.js#49373

阅读整个issue,你会发现有人提供了这样的解决办法:

export const dynamic = 'force-dynamic'
// or
export const revalidate = 0

实测不建议,原因有人在issue中提到了

The export const dynamic = 'force-dynamic line worked for me when placed in my layout.tsx file, but when I navigate to a different page using the useRouter hook, I get the following err:

Error: Dynamic server usage: force-dynamic

解决办法:

  1. 既然声明了SSG,那么就遵循要求,不要在服务端去做任何dynamic action,如果需要做请通过本地client操作,如上图所示
  2. 通过middleware去做权限判断,没有权限统一redirect到指定router

这就意味着:

  • 需要鉴权才能展示请不要用SSG的方式,用SSR代替
  • 如果要SSG,又需要做相应的交互,请在client中进行,参考案例:淘宝宝贝详情页是SSG,销售数据可以client异步获取(仅登录可见),帮助中心文档是SSG,文档点赞和评论可以client异步获取(仅登录可操作)
  • 否则请采用解决办法中的第2条解决