译者 | 布加迪
审校 | 孙淑娟
渲染是将React代码转换成HTML的过程。用户选择的渲染方法取决于所处理的数据以及用户对性能的关注程度。
在Next.js中,渲染的用途非常广泛。用户可以用静态或增量方式渲染客户端或服务器端页面。
看看这些方法是如何工作的以及每种方法有怎样的表现。
服务器端渲染
就服务器端渲染(SSR)而言,当用户访问网页时,浏览器向服务器发送关于该页面的请求。服务器从数据库获取必要的数据(如果需要的话),并将其与页面内容一同发送到浏览器。然后浏览器将其显示给用户。
浏览器对用户点击的每个链接发出此请求,这意味着服务器每次都处理请求。这可能会降低网站的性能。然而,服务器端渲染非常适合使用动态数据的页面。
每当用户请求时,使用getServerSideProps重新构建页面。
export default function Home({ data }) {
return (
<main>
// Use data
</main>
);
}
export async function getServerSideProps() {
// Fetch data from external api
const res = await fetch('https://.../data')
const data = await res.json()
// Will be passed to the page component as props
return { props: { data } }
}
getServerSideProps只在服务器上运行,它是这样运行的:
- 当用户直接访问页面时,它在请求时运行,页面使用它返回的属性来预渲染。
- 当用户通过Next链接访问页面时,浏览器向运行它的服务器发送请求。
在新版本中,用户可以选择使用页面或布局中的动态数据获取来享用服务器端渲染。
动态数据获取是fetch()请求,它通过将缓存选项设置为“no-store”来选择退出缓存。
fetch (https://..。', {cache: 'no-store'});
或者,将revalidate设置为0:
fetch (https://..。', {next: {revalidate: 0}});
该功能目前处于测试阶段,请记住这一点。可以在Next.js 13 Beta文档中进一步了解动态数据获取。
客户端渲染
当用户需要频繁更新数据或不想预渲染页面时,应该使用客户端渲染(CSR)。用户可以在页面层面或组件层面实现CSR。在页面层面,Next.js在运行时获取数据;而在组件层面执行操作时,它在页面挂载时获取数据。正因为如此,CSR可能导致性能变慢。
使用useEffect()钩子在客户端渲染页面,如下所示:
import { useState, useEffect } from 'react'
function Home() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('/api/get-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (isLoading) return <p>Loading...</p>
if (!data) return <p>No data</p>
return (
<div>
// Use data
</div>
)
}
还可以使用SWR钩子。它缓存数据,一旦数据过时,就重新验证数据。
import useSWR from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json())
function Home() {
const { data, error } = useSWR('/api/data', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<div>
// Use data
</div>
)
}
在Next.js 13中,用户需要使用客户端组件,为此在文件顶部添加“use client”指令。
"use client";
export default () => {
return (
<div>
// Client component
</div>
);
};
SSR和CSR的区别在于,在SSR中,从服务器上的每个页面请求获取数据;而在CSR中,从客户端获取数据。
静态站点生成
就静态站点生成(SSG)而言,页面在构建期间只获取一次数据。静态生成页面非常快,性能良好,因为所有页面都事先构建。SSG因此非常适合使用静态内容(比如销售页面或博客)的页面。
在Next.js中,用户必须从想要静态渲染的页面中导出 getStaticProps函数。
export default function Home({ data }) {
return (
<main>
// Use data
</main>
);
}
export async function getStaticProps() {
// Fetch data from external API at build time
const res = await fetch('https://.../data')
const data = await res.json()
// Will be passed to the page component as props
return { props: { data } }
}
用户还可以在getStaticProps里面查询数据库。
export async function getStaticProps() {
// Call function to fetch data from database
const data = await getDataFromDB()
return { props: { data } }
}
在Next.js 13中,静态渲染是默认操作,内容被获取和缓存,除非用户关闭了缓存选项。
async function getData() {
const res = await fetch('https://.../data');
return res.json();
}
export default async function Home() {
const data = await getData();
return (
<main>
// Use data
</main>
);
}
可从文档进一步了解Next.js 13中的静态渲染。
增量静态生成
有时用户想使用SSG,但又想定期更新内容,这时候增量静态生成(ISG)大有帮助。
ISG让用户可以在构建静态页面后在指定的时间间隔后创建或更新静态页面。这样一来,用户不需要重建整个站点,只需重建需要它的页面。
ISG保留了SSG的优点,又增加了为用户提供最新内容的好处。ISG非常适合站点上那些使用不断变化的数据的页面。比如说,用户可以使用ISR渲染博文,以便在编辑文章或添加新文章后博客保持更新。
若要使用ISR,将revalidate属性添加到页面上的getStaticProps函数中。
export async function getStaticProps() {
const res = await fetch('https://.../data')
const data = await res.json()
return {
props: {
data,
},
revalidate: 60
}
}
在这里,当请求在60秒后到来时,Next.js将尝试重新构建页面。下一个请求将产生带有更新页面的响应。
在Next.js 13中,使用fetch中的revalidate,就像这样:
fetch (https://..。/data', {next: {revalidate: 60}});
用户可以将时间间隔设置为最适合其数据的任何时间间隔。
如何选择渲染方法?
到目前为止,用户已了解了Next.js中的四种渲染方法:CSR、SSR、SSG和ISG。每种方法都适用于不同的情况。CSR适用于需要新数据的页面。SSR适用于使用动态数据的页面,但它对SEO较为友好。
SSG适合数据基本上静态的页面,而ISG最适合含有用户想要间隔更新的数据的页面。SSG和ISG从性能和SEO方面来说都很出色,因为数据预获取,用户还可以缓存数据。
原文标题:Understanding Next.js Rendering Methods: CSR, SSR, SSG, ISR,作者:Mary Gathoni