这个问题比较复杂,我一点一点回答你。
先讨论正式版,再讨论部分预预渲染
1.next dev 和 build 的渲染逻辑是不一样的,如果你把 data.ts 中 dashboard 相关的那三个组件的 noStore 注释掉,然后 build 一下,你会发现 /dashboard 生成的是静态页面,因为页面没有动态函数而且数据都 cached 了,但 dev 的时候情况可能不一样,数据可能没有全部 cache 完,或者说每次刷新的时候都会重新请求相关数据,这样其实更符合逻辑。注意,你加不加 suspense 都不会影响静态渲染
2.在正式版中,如果你给那三个组件中任意一个加上了 noStore ,整个 dashboard 页面,包括那三个组件都会退出静态渲染,这一点也并不难理解,回顾官方定义,再考虑一下目前渲染路线其实就两种,组件又在页面之中,next 在 build 的时候遇到 noStore 就知道下一步该选什么渲染路线。
> unstable_noStore 可用于以声明方式选择退出静态渲染并指示不应缓存特定组件。
3.你希望达成什么?我想应该是不能够每次刷新都去查询数据,最好可以手动 revalidateTag 。
有两个函数,可能可以帮到你,react cache 和 unstable_cache
https://nextjs.org/docs/app/building-your-application/caching#react-cache-functionhttps://nextjs.org/docs/app/api-reference/functions/unstable_cache你可以现在就试试,记得随便一个组件上加上 noStore,然后在 RevenueChart 组件上创建一个函数,
import { unstable_cache} from 'next/cache';
const getCachedRevenue = unstable_cache(
async () => fetchRevenue(),
['Revenue']
);
组件内部开头删掉
const revenue = await fetchRevenue()
然后这样写,
const revenue = await getCachedRevenue()
先 build,start,然后进 dashboard ,在刷新的时候,你会发现,Revenue 组件会保持不变,另外两个出现了骨架屏,可以换个浏览器或者进隐私窗口,一样是秒开。
4.关于你的第二点,没看太明白,这个 30s,5 分钟之类的,都是客户端缓存,你在开发者工具的网络选项卡把选一下禁用缓存,第三点的效果不会变,多看看文档这一节,
https://nextjs.org/docs/app/building-your-application/caching#overview5.最后再来说一下部分预渲染,
根据,
https://nextjs.org/docs/app/api-reference/functions/unstable_noStore在 unstable_cache 内使用 unstable_noStore 不会选择退出静态生成。相反,它将根据缓存配置来确定是否缓存结果。
这句话不太好懂,不过我实测的结果就是,如果你是正式版,那么无论你任何地方使用了 noStore ,在 build 的时候,路线都会变成动态,而如果你是 canary,想要使用部分预渲染,最好还是不要在 unstable_cache 缓存的函数内使用 noStore,参考
https://nextjs.org/docs/messages/ppr-caught-error ,
> 确保您没有将选择动态渲染的 Next.js API 包装在 try/catch 块中。
尽管官方建议,可以在 try...catch 前插入 noStore, 但后面实现缓存函数不太方便,所以我个人建议,可以在组件的第一行,也就是 const revenue = await getCachedRevenue()的上面一行,使用 noStore ,第二行用 cache,逻辑也比较清晰。
同时,根据,
https://nextjs.org/docs/app/api-reference/next-config-js/partial-prerendering ,
你需要 npm install next@canary ,然后改 config (这个我看有注释),记得每个组件都要加上 noStore ,不然参考第一条,就会被当成静态内容一次生成哦(关于哪些内容被生成静态的了,你可以去开发者工具的网络选项卡,预览第一个送过来的 Document ),然后可以 build 了哦。
祝好!
其他参考(不分先后,我也没看(完),不过很值得看):
-
https://github.com/vercel-labs/next-partial-prerendering-
https://github.com/orgs/vercel/discussions/4696-
https://codedrivendevelopment.com/posts/rarely-known-nextjs-features-
https://github.com/vercel/next.js/pull/56930-
https://stackoverflow.com/questions/76829076/in-next-js-13-app-router-how-can-i-use-data-caching-when-not-using-fetch-but-
https://github.com/vercel/next.js/discussions/54075