了解 Next.js 数据获取(CSR、SSR、SSG、ISR)
当我开始学习 Next.js 时,我被一堆看起来相似的缩写弄得晕头转向,不知道它们是什么,也不知道它们有什么区别。这很容易让人困惑,因为在使用 Create React App 时,我们通常只使用一种策略从 API 中获取数据,那就是使用useEffect
。
Next.js 有多种数据获取策略。尽管 Next.js 最初以服务器端渲染框架而闻名,但事实证明 Next.js 有 4 种数据获取方法。以下是对每种方法的简要说明,以便您熟悉 CSR、SSR、SSG 和 ISR 这几个缩写。
- CSR - 客户端渲染,这是通常使用的数据获取类型,它将在客户端的
useEffect
每个页面请求中从 API 获取数据(页面渲染后,该函数将运行)。 - SSR - 服务器端渲染,将运行一个特殊函数来从服务器端的每个页面请求的 API 中获取数据(在页面加载之前,该特殊函数将首先运行,产生延迟,然后再为页面提供服务)。
- SSG——静态站点生成,当该页面构建时将运行一个特殊函数来获取数据。
- ISR – 增量静态再生,这是一个新事物,简而言之,是 SSG 和 SSR 的组合,它以静态方式提供服务,但在特定时间和特定条件下,页面将重建并再次从 API 中获取数据。
如果您不明白,请不要担心,因为我将进行彻底的解释,只需先熟悉一下单词即可。
我之前提到过,使用特定的数据获取方法时会运行一个特殊函数。请记住这一点,我将向您展示这个特殊函数是什么。
此代码示例将使用 axios 从 API 获取日期时间,然后将其渲染到页面上。查看日期时间非常有用,这样我们才能真正了解 API 的调用时间。
客户端渲染(CSR)
特殊功能:useEffect
代码示例
export default function CSRPage() {
const [dateTime, setDateTime] = React.useState<string>();
React.useEffect(() => {
axios
.get('https://worldtimeapi.org/api/ip')
.then((res) => {
setDateTime(res.data.datetime);
})
.catch((error) => console.error(error));
}, []);
return (
<main>
<TimeSection dateTime={dateTime} />
</main>
);
}
演示
条款:
- PT → 预览时间,即 API 被点击时显示的时间。可以在中间看到。
- RT → 实时,每秒更新的真实滴答时间,可以在右下角看到
视频说明:
- 页面于实时 (RT) 15:46:03 重新加载,然后显示“正在加载”指示
- 大约 1 秒后,预览时间显示 15:46:04(太平洋时间)
强调的关键
- useEffect 函数,该函数是页面正在使用客户端渲染的关键指标。
- LOADING 指示,因为数据获取是在页面渲染完成后进行的,数据并不是立即获取的,因此显示为加载状态。
- 每次页面请求时都会获取数据,这就是每次重新加载显示的时间不同的原因。
服务器端渲染(SSR)
特殊功能:getServerSideProps
代码示例
export default function SSRPage({ dateTime }: SSRPageProps) {
return (
<main>
<TimeSection dateTime={dateTime} />
</main>
);
}
export const getServerSideProps: GetServerSideProps = async () => {
const res = await axios.get('https://worldtimeapi.org/api/ip');
return {
props: { dateTime: res.data.datetime },
};
};
演示
视频说明:
- 在 16:32:38(RT)点击链接,稍停顿 2 秒,然后页面加载显示 16:02:40(PT)
强调的关键
- getServerSideProps 函数,该函数是页面是否使用服务器端渲染的关键指标。
- 渲染前延迟,且无加载指示,数据在页面渲染前获取,因此此时API 被调用时会有轻微延迟,然后页面将显示无加载指示
- 每次页面请求时都会获取数据,这就是每次重新加载显示的时间不同的原因。
CSR 与 SSR
这是 CSR 与 SSR 之间的区别,请留意延迟和加载指标。
视频说明:
- 单击 CSR 时,立即会出现一个 LOADING 文本,显示一秒钟,然后预览时间加载。
- 点击 SSR 时,出现轻微延迟,然后页面加载。
强调的关键
- 页面加载后,CSR 访问 API。
- SSR 在页面加载之前就访问了 API。
简短的补充
我可能会另写一篇文章来分析每种方法的优缺点,但使用CSR时SEO 效果并不好,因为数据只会在页面渲染后才获取。当我们创建带有门控身份验证的页面时,这很有用也很方便,因为像仪表盘、编辑个人资料页面等页面实际上不需要 SEO。
但是,对于服务器端渲染 (SSR) 来说,虽然会造成延迟,但已获取的数据会被注入,从而有助于 SEO。这对于需要吸引流量的帖子或帖子(例如 Reddit 等)非常有用。
静态站点生成 (SSG)
特殊功能:getStaticProps
代码示例
export default function SSGPage({ dateTime }: SSGPageProps) {
return (
<main>
<TimeSection dateTime={dateTime} />
</main>
);
}
export const getStaticProps: GetStaticProps = async () => {
const res = await axios.get('https://worldtimeapi.org/api/ip');
return {
props: { dateTime: res.data.datetime },
};
};
演示
视频说明:
- 预览时间为 13:39:36(太平洋时间)。但实际时间为 16:16:59(实时时间),比实际时间晚了大约 3 小时。
- 重新加载并返回主页没有任何改变。
强调的关键
- getStaticProps 函数,该函数是页面使用静态站点生成的关键指标。
- 运行时获取
yarn build
,API仅在应用程序构建时才会被调用。这就是为什么当前时间为 13:39,而实际时间为 16:17。 - 由于没有进一步的获取,数据不会改变,这就是为什么每次重新加载显示的时间都相同。
增量静态再生
特殊功能:getStaticProps
+revalidate
代码示例
export default function ISR20Page({ dateTime }: ISR20PageProps) {
return (
<main>
<TimeSection dateTime={dateTime} />
</main>
);
}
export const getStaticProps: GetStaticProps = async () => {
const res = await axios.get('https://worldtimeapi.org/api/ip');
return {
props: { dateTime: res.data.datetime },
revalidate: 20,
};
};
演示
免责声明:重新验证时间设置为 20 秒。
视频说明:
- 最初是 16:40:12(PT),重新加载时的实际时间是 16:40:25(RT) 和 16:40:29(RT)。在这两次重新加载中,预览时间 (PT) 没有变化。
- 然后,在 16:40:32(RT)(初始加载后 20 秒)时,会重新加载两次,第一次分别在 16:40:36(RT) 和 16:40:40(RT)。第二次加载后,预览时间更改为 16:40:37(PT) 。
强调的关键
现在,这可能会让您感到困惑,但这是我希望您看一下的关键。
- 当 20 秒的冷却时间跨度为 16:40:12(RT) - 16:40:32(RT) 时,重新加载不会触发更改。这是因为页面处于冷却状态,正如我们在
revalidate
按键上设置的一样。 - 20 秒冷却时间 - 16:40:32(RT)后,我们进行了 2 次重新加载。
- 首次重新加载时间为 16:40:36(RT),我们知道它不再处于冷却状态。冷却状态关闭后的首次访问将触发页面重建。页面重建的意思是,只有特定页面会被重建,而不是整个应用程序。Fetch API 将在后台运行,但预览时间不会有任何变化。
- 第二次完全刷新时间为 16:40:40(实时时间),预览时间更改为 16:40:37(太平洋时间)。恰好是页面重建后一秒(这意味着重建大约需要 1 秒)。第二次刷新将服务于上次刷新后重建的页面。
重新访问页面 vs 完全重新加载
条款:
- 重新访问页面 → 使用下一个/链接导航(返回主页,然后再次返回该页面)
- 完全重新加载 → 在网站上重新加载(command+r)
视频说明:
- 第一次在 18:38:45(RT) 重新访问页面,会触发重建,但第二次重新访问后,预览时间没有变化。
- 完全重新加载后,预览时间将更改为 18:38:45(太平洋时间)
笔记:
- 第一次重新加载不必是完全重新加载,我们可以返回主页,然后再次回到该页面(重新访问),只要我们不处于冷却状态,它就会触发重建。
- 但是,第二次重新加载必须是完全重新加载。返回主页,然后再次返回该页面不会改变新的预览时间。
现在,我们假设只有一个人访问网站。但是,每次访问都会重新加载,同时仍然遵循冷却状态。
那么它每 20 秒就会重建一次吗?
不。
当冷却时间关闭时,如果没有人访问该页面,那么该页面将不会重建,即使过了 20 多秒也是如此。
但是,当冷却状态为 关闭时,第一个访问的用户将触发重建。该用户将看不到更改。但是,这些更改将在下一次完全重新加载时生效。
结论
就这样吧,朋友们!
如果你已经理解了这些内容,我建议你阅读更多关于如何在它们之间进行选择的文章。我提供了4个指标供你参考,并提供了一些示例!
文章来源:https://dev.to/theodorusclarence/understanding-next-js-data-fetching-csr-ssr-ssg-isr-1nff