在默认情况下,Next.js 会预渲染每个页面。这意味着 Next.js 会提前为每个页面生成 HTML,而不是全部由客户端 JavaScript 完成。预渲染可以带来更好的性能和SEO(Search engine optimization,搜索引擎优化)。
每个生成的 HTML 都与该页面所需的最少 JavaScript 代码相关。当浏览器加载页面时,其 JavaScript 代码将运行并使页面完全交互。(这个过程称为hydration,水合作用。)
Next.js的预渲染分为两种形式:Static Generation和Server-side Rendering。其中, Static Generation 又分为 with data, 和 without data 两种情况。接下来我会分别讲讲每一种情况。
Next.js 有两种pre-rendering形式,Static Generation和 Server-side Rendering,以下是官方的解释:
开发模式下(运行
npm run dev
或yarn dev
时),页面在每次request的时候预渲染。 这也适用于静态生成,使其更易于开发。 投入生产时,静态生成将在构建时发生一次,而不是在每次请求时发生。我们可以分别为每个page设置pre-rendering形式
你应该问问自己:“我可以在用户请求之前预渲染此页面吗?” 如果答案是肯定的,那么你应该选择Static Generation。
Static Generation can be done with and without data.
静态生成有以下两种pre-rendering
方式:
对于某些页面,如果不首先获取一些外部数据,可能无法呈现 HTML。也许需要在构建时访问文件系统、获取外部 API 或查询数据库。Next.js开箱即用地支持这种情况——带数据的静态生成
getStaticProps
在 Next.js 中,导出页面组件时,你可以导出一个名为getStaticProps
的async
function(异步函数)。
getStaticProps
在生产中的 构建 时运行例如:
export default function Home(props) { ... }
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
这是一段官网解释:
Essentially,
getStaticProps
allows you to tell Next.js: “Hey, this page has some data dependencies — so when you pre-render this page at build time, make sure to resolve them first!”Note: In development mode,
getStaticProps
runs on each request instead.
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..');
return res.json();
}
import someDatabaseSDK from 'someDatabaseSDK'
const databaseClient = someDatabaseSDK.createClient(...)
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from a database
return databaseClient.query('SELECT posts...')
}
getStaticProps
只在服务器端运行。它永远不会在客户端运行。它甚至不会包含在浏览器的 JS 包中。这意味着你可以编写直接数据库查询等代码,而无需将它们发送到浏览器。
在开发(
npm run dev
或yarn dev
)中,getStaticProps
在 每个请求(request) 上运行。 在生产中,getStaticProps
在 构建时 运行。但是,可以使用getStaticPaths
返回的fallback
key 来增强此行为
getStaticProps
只能从page导出。不能从non-page文件中导出它。
由于静态生成在 build 时发生一次,因此它不适合频繁更新或根据每个用户请求更改的数据。
如果你的数据可能会发生变化,你可以使用服务器端渲染。
为了使用 Server-side Rendering 你需要从页面导出 getServerSideProps
方法 而不是之前 提到的 getStaticProps
方法。
仅当你需要预渲染的数据必须在请求时获取,才应使用getServerSideProps
。
这么做,用户接收到页面第一个字节所花费的时间time to first byte (TTFB) 会比 getStaticProps
长,因为服务器要计算每一个request的结果, 并且如果没有额外配置, CDN无法缓存结果。
export async function getServerSideProps(context) {
return {
props: {
// props for your component
},
};
}
getServerSideProps
在请求时被调用,它的参数 ( context
) 包含请求特定的参数。
如果不需要预渲染data, 指仅预渲染page,可能由于data时效性要求很高,不需要预渲染data,也可以使用Client-side Rendering ,比如,在dashboard用户仪表板场景中,dashboard是私有的、特定于用户的页面,所以 SEO不相关,且不需要在服务器端预渲染(不知道用户信息,预渲染无意义);数据更新频繁,需要请求时取数据。
与 SEO 无关的私人的、用户特定的页面
比如,在dashboard用户仪表板场景中,dashboard是私有的、特定于用户的页面,所以 SEO不相关,且不需要在服务器端预渲染(不知道用户信息,预渲染无意义);数据更新频繁,需要请求时取数据。
如果在客户端获取数据,可以使用Next.js团队出的SWR,这是一个React Hook,它处理缓存、重新验证、焦点跟踪、间隔重新获取等。
示例:
import useSWR from 'swr';
function Profile() {
const { data, error } = useSWR('/api/user', fetch);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return <div>hello {data.name}!</div>;
}
查看SWR 文档以了解更多信息。