Next.js14从入门到实战013:NextJS基础篇之静态和动态渲染
在上一章中,您为dashboard页面获取了数据。不过,我们简要讨论了当前设置的两个局限性:
- 数据请求正在无意中形成瀑布效应。
- 仪表板是静态的,因此任何数据更新都不会反映在您的应用程序上。
在本章中,你将学习……
- 什么是静态渲染以及静态渲染如何提高应用程序的性能。
- 什么是动态渲染以及何时使用。
- 让仪表盘充满活力的不同方法
- 模拟缓慢的数据获取,看看会发生什么。
什么是静态渲染?
使用静态渲染时,数据获取和渲染会在构建时(部署时)或重新验证时在服务器上进行。然后可以在内容分发网络(CDN)中分发和缓存结果。
每当用户访问您的应用程序时,缓存结果就会送达。静态呈现有几个好处:
- 更快的网站:可对预渲染内容进行缓存和全球分发。这可确保世界各地的用户更快、更可靠地访问您的网站内容。
- 减少服务器负载:由于内容是缓存的,因此服务器无需为每个用户请求动态生成内容。
- 搜索引擎优化:预渲染内容更容易被搜索引擎爬虫索引,因为页面加载时内容已经可用。这可以提高搜索引擎的排名。
静态渲染适用于没有数据或用户之间共享数据的用户界面,如静态博客文章或产品页面。对于有定期更新的个性化数据的仪表盘来说,静态呈现可能并不合适。
与静态渲染相反的是动态渲染。
什么是动态渲染?
通过动态呈现,服务器会在请求时(用户访问页面时)为每个用户呈现内容。动态呈现有几个好处:
- 实时数据:动态渲染可让您的应用程序显示实时或经常更新的数据。这非常适合数据经常变化的应用。
- 用户特定内容:提供仪表盘或用户配置文件等个性化内容,并根据用户互动更新数据,变得更加容易。
- 请求时信息:动态呈现允许您访问只能在请求时才能知道的信息,如 cookie 或 URL 搜索参数。
让仪表盘充满活力
默认情况下, @vercel/postgres
不设置自己的缓存语义。这允许框架设置自己的静态和动态行为。
您可以在服务器组件或数据获取函数中使用名为 unstable_noStore
的 Next.js API,以选择退出静态模式。让我们添加以下内容。
在 data.ts
中,从 next/cache
导入 unstable_noStore
,并在数据获取函数的顶部调用它:
// /app/lib/data.ts
// ...
import { unstable_noStore as noStore } from 'next/cache';
export async function fetchRevenue() {
// Add noStore() here to prevent the response from being cached.
// This is equivalent to in fetch(..., {cache: 'no-store'}).
noStore();
// ...
}
export async function fetchLatestInvoices() {
noStore();
// ...
}
export async function fetchCardData() {
noStore();
// ...
}
export async function fetchFilteredInvoices(
query: string,
currentPage: number,
) {
noStore();
// ...
}
export async function fetchInvoicesPages(query: string) {
noStore();
// ...
}
export async function fetchFilteredCustomers(query: string) {
noStore();
// ...
}
export async function fetchInvoiceById(query: string) {
noStore();
// ...
}
模拟慢速数据读取
使仪表盘动态化是第一步。但是......我们在上一章中提到过一个问题。如果一个数据请求比其他所有请求都慢,会发生什么情况?
让我们来模拟一次缓慢的数据获取。在 data.ts
文件中,取消 console.log
和 setTimeout
中 fetchRevenue()
的注释:
// /app/lib/data.tx
export async function fetchRevenue() {
try {
// We artificially delay a response for demo purposes.
// Don't do this in production :)
console.log('Fetching revenue data...');
await new Promise((resolve) => setTimeout(resolve, 3000));
const data = await sql<Revenue>`SELECT * FROM revenue`;
console.log('Data fetch completed after 3 seconds.');
return data.rows;
} catch (error) {
console.error('Database Error:', error);
throw new Error('Failed to fetch revenue data.');
}
}
现在在新标签页中打开 http://localhost:3000/dashboard/
,注意页面加载所需的时间。在终端中,你还应该看到以下信息:
Fetching revenue data...
Data fetch completed after 3 seconds.
在这里,你人为地添加了 3 秒钟的延迟来模拟缓慢的数据获取。这样做的结果是,在获取数据的过程中,整个页面都被阻塞了。
这就给我们带来了开发人员必须解决的一个共同难题:采用动态渲染后,应用程序的速度只能与最慢的数据获取速度相当。
转载自:https://juejin.cn/post/7361064330170007587