浏览器访问网站典型的流程是,浏览器首先获取一个HTML 页面,此页面并没有数据,然后 useEffect
函数调用 fetch
从服务器获取数据,然后使用这些数据设置组件 state,state 因为发生改变,react 使组件函数重新执行一遍,页面因此重新渲染,因此页面实际上有两个渲染周期。
而 SEO (search engine optimization 搜索引擎优化)依据的是第一个渲染周期的页面,此页面数据为空,为了避免这个问题,可以使得预渲染的页面,在第一个 render cycle 就已包含从数据库中获取的数据。
要使得预渲染的页面包含数据,NextJS 提供了两种形式的预渲染:
- static site generation 静态生成 SSG
- server-side rendering 服务端渲染 SSR
SSR 使用 getStaticProps
函数在build时就会生成含有数据的页面, sample code:
import MeetupList from "./../components/meetups/MeetupList";
const DUMMY_MEETUPS = [
{
id: "m1",
title: "A First Meetup",
image:
"https://www.safari254.com/wp-content/uploads/2014/08/3-unmissable-experiences-Nairobi_KICC-sunset.jpg",
address: "Somewhere, 12345",
description: "The sunset of an African city",
},
];
function HomePage(props) {
return <MeetupList meetups={props.meetups} />;
}
export async function getStaticProps() {
// 此函数中可以写各种服务端代码:连数据库,访问文件系统.....
// 这里的 DUMMY_MEETUPS 一般是从服务端获取的数据
return {
props: {
meetups: DUMMY_MEETUPS,
},
revalidate: 123,
};
}
export default HomePage;
getStaticProps
只能在page 组件中使用。getStaticProps
函数名称固定,必须返回一个对象,对象必须含有props
属性,此props
用于组件渲染。getStaticProps
可以是异步的, 可以返回 promise。getStaticProps
可以访问文件系统,可以连数据库。写在这个函数中的代码在build阶段就执行过了,不会到达客户端,不会在服务器上执行,尤其不会在客户端执行。所以这些代码永远不会到达访问者的机器。
使用静态生成意味着,在部署之后, 预渲染的页面不会改变,至少默认不会改变。如果数据变了,那么就需要重新build一遍,重新部署一遍。不这样做页面数据会过时。为了解决这个问题,在 getStaticProps
返回的对象中设置 revalidate
属性,值为时间,单位为秒。使用 revalidate
属性就可以应用叫做增量式静态生成(incremental static generation) 的功能,然后服务端每间隔设置的时间段后重新生成一遍页面。时间可以根据页面数据实际更新速度设定。例如设置 revalidate: 123
, 就可以保证,页面过时不会超过 123
秒。