更新于:23.12.08
回想一下传统的SSG页面中,如何加载动态内容,比如商品页加最近30天购买数,文章页加评论信息,信息流加推荐。
- 传统的做法: 静态部分渲染出来,比如宝贝描述、文章内容、推流内容等,然后在客户端异步获取动态内容
而PPR则是:
- 将这一部分挪到了服务器上,将静态部分渲染出来
- 然后动态的内容通过
Suspense包裹,NextJS将会通过占位的方式优先进行渲染 - 随后通过推流替换占位内容
目前有5种模式渲染,具体根据情况灵活运用,没有最好或最合适
更新于:23.11.07
- 总结:NextJS默认以静态模式,或试图最大化静态模式进行渲染
- 区别
- 静态渲染:是指在构建时或请求前预先缓存,在下次请求优先读取缓存作为响应
- 动态渲染:需要经过服务器进行计算渲染,给出响应结果
- 3种动态渲染行为:
- 关于服务端
fetch[总结]fetch和视图(component tree)是两条单独的缓存路线fetch默认也是在构建时静态缓存,一旦缓存之后所有请求都直接从缓存中读取给出响应- 除非声明fetch动态渲染:
no-store、revalidate
- 综上所述,如何判断当前路由段是动态还是静态:
- 看url对应的目录、看路由段声明、看动态函数、看
fetch是否有额外声明 - 如果都没有,那么就是静态
- 再回想下自己的业务页面所需哪些功能,采用哪种渲染是不是清晰多了?
- 看url对应的目录、看路由段声明、看动态函数、看
- 通过以上总结再来看NextJS的几个渲染模式
- SSG:静态渲染,包括有
generateStaticParams和静态的single page - SSR:含动态路由、方法、声明、动态
fetch - ISR:带有时间间隔的缓存SSR
- CSR:
hydrate后在client side进行interactive部分 - PPR:混合动态和静态渲染部分
- SSG:静态渲染,包括有
- NextJS默认所有
page都是SSG,需要通过调用动态函数cookies、headers,或者通过声明revalidate、dynamic转换为SSR - 可以通过
generateStaticParams去声明SSG的渲染范围 - 无论
SSG还是SSR,服务端所有的fetch都将在build前以SSG方式完成加载,build之后不再请求,除非将fetch采用cache: 'no-store模式(具体看上述fetch总结) no-store模式下,通过revalidate实现ISRSSR+use client实现CSR,SSG在build后可采用CSR方式对边缘计算做交互
SSG的坑点:
- 随着NextJS 14增加的PPR模式,这个坑点将可能不复存在 [查看ppr模式]
SSG不能动态渲染的问题请通过PPR解决
一旦通过generateStaticParams去声明SSG渲染,无论是在page中,还是在page上方的布局中,请不要在服务端去调用cookies和headers这样的动态函数,否则会报错[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-dynamicline worked for me when placed in mylayout.tsxfile, but when I navigate to a different page using theuseRouterhook, I get the following err:
Error: Dynamic server usage: force-dynamic
解决办法:
- 既然声明了
SSG,那么就遵循要求,不要在服务端去做任何dynamic action,如果需要做请通过本地client操作,如上图所示 - 通过
middleware去做权限判断,没有权限统一redirect到指定router
这就意味着:
- 需要鉴权才能展示请不要用
SSG的方式,用SSR代替 - 如果要
SSG,又需要做相应的交互,请在client中进行,参考案例:淘宝宝贝详情页是SSG,销售数据可以client异步获取(仅登录可见),帮助中心文档是SSG,文档点赞和评论可以client异步获取(仅登录可操作) - 否则请采用解决办法中的第2条解决

