更新于: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
实现ISR
SSR
+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-dynamic
line worked for me when placed in mylayout.tsx
file, but when I navigate to a different page using theuseRouter
hook, 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条解决