Next.js - SSR / SSG / CSR / ISR / Dynamic Routing

Next.js 提供了多種網(wǎng)頁渲染方式,這取決于你的服務(wù)應(yīng)用的場景,包括服務(wù)端渲染、客戶端渲染、靜態(tài)生成、增量靜態(tài)生成等。

SSR (Server-side Rendering)

Next.js 中使用 getServerSideProps 來實現(xiàn)服務(wù)端渲染,該動作在用戶發(fā)起頁面請求時執(zhí)行,示例代碼如下:

function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page

兩種模式:

  • 用戶直接請求:服務(wù)端請求數(shù)據(jù) -> 服務(wù)端渲染頁面 -> 用戶
  • 用戶通過 next/linknext/router 跳轉(zhuǎn):客戶端請求數(shù)據(jù) -> 服務(wù)端執(zhí)行 getServerSideProps 并返回數(shù)據(jù) -> 客戶端渲染

SSG (Static-side Generation)

Next.js 中使用 getStaticProps 來實現(xiàn)靜態(tài)頁面生成,該動作在 next build 時執(zhí)行,示例代碼如下:

// posts will be populated at build time by getStaticProps()
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
  // Call an external API endpoint to get posts.
  // You can use any data fetching library
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

export default Blog

CSR (Client-side Rendering)

客戶端渲染,一般的做法是在 useEffect 中請求服務(wù)端數(shù)據(jù)再渲染組件,該動作在頁面基本靜態(tài)文件加載完畢后執(zhí)行,示例代碼如下:

function Profile() {
  const [data, setData] = useState(null)
  const [isLoading, setLoading] = useState(false)

  useEffect(() => {
    setLoading(true)
    fetch('/api/profile-data')
      .then((res) => res.json())
      .then((data) => {
        setData(data)
        setLoading(false)
      })
  }, [])

  if (isLoading) return <p>Loading...</p>
  if (!data) return <p>No profile data</p>

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.bio}</p>
    </div>
  )
}

Next.js 背后的技術(shù)團隊開發(fā)了名為 SWR 的 React Hook 包,如果使用客戶端渲染的話,強烈推薦使用 SWR,它可以處理緩存、重新驗證、焦點跟蹤、間隔重新獲取等。示例代碼如下:

import useSWR from 'swr'

const fetcher = (...args) => fetch(...args).then((res) => res.json())

function Profile() {
  const { data, error } = useSWR('/api/profile-data', fetcher)

  if (error) return <div>Failed to load</div>
  if (!data) return <div>Loading...</div>

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.bio}</p>
    </div>
  )
}

想了解更多,可以查看 SWR 文檔 。

ISR (Incremental Static Regeneration)

Next.js 中使用增量靜態(tài)生成,只需在 getStaticProps 中添加屬性 revalidate,該動作在用戶發(fā)起頁面請求時執(zhí)行,示例代碼如下:

function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 10 seconds
    revalidate: 10, // In seconds
  }
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// the path has not been generated.
export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: blocking } will server-render pages
  // on-demand if the path doesn't exist.
  return { paths, fallback: 'blocking' }
}

export default Blog

如上示例,用戶發(fā)起請求后,服務(wù)端會渲染并緩存該頁面,再將預(yù)渲染的頁面返回給用戶。在緩存期間內(nèi),用戶的請求會直接返回緩存;緩存時間結(jié)束后,用戶再次請求,會重新渲染并生成新的緩存。

使用 ISR,就可以在運行時實現(xiàn)靜態(tài)頁面生成,而無需重新構(gòu)建整個網(wǎng)站。

Dynamic Routing

Next.js 中配合使用 getStaticPaths + getStaticProps 即可實現(xiàn)動態(tài)路由的預(yù)渲染,該動作在 next build 時執(zhí)行,示例代碼:

/**
 * CodePath: ./pages/user/[uid].tsx
 */
import { GetStaticPropsContext } from "next/types"

const Page = ({ name }) => {

  return (
    <div> {name} </div>
  )

}

export async function getStaticPaths() {
  const users = ['Anoyi', 'Jack', 'Marry']
  return {
    paths: users.map(user => ({ params: { user } })),
    fallback: true
  };
}

export async function getStaticProps(context: GetStaticPropsContext) {

  const { user } = context.params

  return {
    props: {
      user
    },
  }

}

export default Page

如上示例,項目構(gòu)建完畢后,會生成三個靜態(tài)文件 /user/Anoyi & /user/Jack & /user/Marry,其它路由會執(zhí)行動態(tài)路由的邏輯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容