Next.js - 静态站点生成
Static Site Generation 是 Next.js 中使用的一种优化技术,通过它可以在用户界面上快速渲染 HTML 页面。在本章中,我们将学习什么是静态站点生成、静态站点生成的优点,以及如何在从外部源获取数据时实现静态站点生成。
什么是静态渲染?
Static Rendering(或 Static Site Generation)是一种服务器渲染策略,在构建应用程序时生成 HTML 页面。这意味着在生产环境中,当运行 'next build' 时生成 HTML 页面。此 HTML 将在每个请求中被重用。
- 在 Static Rendering 中,HTML 页面只构建一次,然后由 CDN 缓存并几乎即时地提供给客户端。
- 这种渲染方式提升了应用程序的性能和用户体验。
- 默认情况下,所有不涉及从外部源获取数据的 Next.js 组件都遵循静态渲染策略。
- 静态渲染常用于博客页面、文档页面和营销页面。
不获取数据时的静态生成
如上所述,所有不涉及从外部资源获取数据的组件都将静态生成。请查看下面的示例。
示例
这是一个静态的 'About' 页面,对所有用户都是一样的。因此,该页面将在构建时生成一次,然后作为缓存存储。
export default function About() {
return (
<div>
<h1>About Us</h1>
<h2>Welcome to the About page!</h2>
<h4>This page is same for all users</h4>
</div>
);
}
输出
上述代码的输出将是一个简单的 About 部分的 HTML 页面。该页面对所有用户都是一样的。
通过获取外部数据进行静态生成
如果您想在构建时获取数据来创建静态页面,可以使用 'getStaticProps()' 函数。该函数将在构建时获取数据一次,然后基于它创建一个完整的 HTML 文件。此 HTML 文件将提供给所有用户。请查看下面的示例。
示例
在下面的代码中,我们将在构建时使用 'getStaticProps()' 函数获取 API 数据,然后将其作为 prop 传递给 React 组件。
// app/page.tsx
import React from 'react';
// 从 getStaticProps 函数接收 posts prop
export default function Blog({ posts }) {
return (
<div>
<h1>Blog Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
// 导出 getStaticProps 函数,在构建时获取数据
export async function getStaticProps() {
// 模拟从 API 获取数据
const response = await fetch('https://link/to/api');
const posts = await response.json();
return {
props: {
posts, // 这将作为 props 传递给 Blog 组件
},
};
}
输出
在这个输出中,我们在静态页面中显示来自 API 的数据。

动态路由中的静态生成
静态生成也可以用于带有动态路由的页面。动态路由表示页面的路由(即 URL)将依赖于外部来源的数据。例如,你可以创建一个名为 pages/product/[id]/page.tsx 的文件,根据产品的 ID 来显示产品。这将允许你在访问 localhost/product/1 时显示 id 为 1 的产品。
示例
为了处理动态路由 URL,Next.js 允许你从动态页面(在本例中为 pages/product/[id]/page.tsx)中导出一个名为 'getStaticPaths' 的 async function。此函数在构建时被调用,并允许你指定要预渲染的路径。
// pages/product/[id]/page.tsx 文件
// 此函数在构建时被调用
export async function getStaticPaths() {
// 调用外部 API 端点来获取产品 ID
const res = await fetch('https://link/to/api');
const products = await res.json();
// 根据产品获取要预渲染的路径
const paths = products.map((product) => ({
params: { id: product.id.toString() }, // 确保 id 是字符串
}));
// 我们只会在构建时预渲染这些路径。
// { fallback: false } 表示其他路由应返回 404。
return { paths, fallback: false };
}
// 此函数也在构建时被调用
export async function getStaticProps({ params }) {
// params 包含产品 `id`。
// 如果路由是 /product/1,则 params.id 为 1
const res = await fetch(`https://.../product/${params.id}`);
const product = await res.json();
// 通过 props 将产品数据传递给页面
return { props: { product } };
}
// 用于显示产品详情的页面组件
export default function ProductPage({ product }) {
return (
<div>
<h1>Product {product.id}</h1>
<p>This is the product page for item {product.id}</p>
<p>Title: {product.title}</p>
</div>
);
}
输出
这是动态路由的输出。页面会根据从服务器获取的产品 ID 而变化。
何时使用静态站点生成?
静态站点生成适用于以下类型的页面:
- 内容很少变化的页面,例如博客或文档。
- 需要快速加载以提升用户体验和 SEO 的页面。
- 可以容忍数据略微过时的页面,因为更新需要重新构建站点。