Next.js中的渲染方式(SSG、SSR、ISR、CSR)

CSR: 客户端渲染(Client-side Rendering)

渲染工作主要交由客户端去完成。
这也是在一般情况下我们使用React的方式。浏览器从服务端接收html和javascript文件,
并通过javascript发送请求,获取数据,使用数据完成渲染工作。

客户端渲染存在一定的缺点:
由于渲染依赖于服务端javascript的下载处理以及请求数据的返回,在此之前页面内容并不会显示完全。
这也同时导致了SEO问题。

Next.js默认进行提前渲染,页面HTML是在服务端提前生成的,
当页面被使用时,服务端会直接返回处理好的HTML静态页面。

在Next.js中使用客户端渲染:

  • 不使用服务端渲染的api:如getServerSideProps;
  • 渲染使用的数据使用useEffect() 配合axios 或者fetch 等去获取;
import React, { useState, useEffect } from 'react'
 
export default function Page() {
  const [data, setData] = useState(null)
 
  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch('https://...')
      setData(res)
    }
  }, [])
 
  return <div>{data}</div>
}

SSR:服务端渲染(Server-side Rendering)

渲染工作主要在服务端进行。
通过服务端去发出数据请求,数据返回后在服务端去处理成一个完整的页面,
处理完成之后直接给客户端返回HTML。
这种方式会带来更好的首屏加载速度,有利于优化SEO,
并且由于客户端并不能直接去获取页面数据,提高了安全性。
当然由于在服务端完成的工作增加,服务端压力会提升,
并且由于浏览器需要等待服务端处理页面,服务端的响应时间可能会相应的增加。

在Next.js中使用服务端渲染:
1.在组件文件中暴露一个async函数getServerSideProps;
2.在getServerSideProps中请求数据并将返回的数据通过props传递给Page组件;

export default function Page({ data }) {
  // 渲染数据...
}
​
export async function getServerSideProps() {
  // 从外部 API 获取数据
      const res = await fetch('https://...')
      const data = await res.json()
  // 使用props给组件传递数据
  return { props: { data } }
}

SSG:静态站点生成(Static Site Generation)

当页面内容不是动态生成,或者需要实时交互情况下,比如一个纯展示页面,而不是聊天页面。
此时直接在构建打包阶段,就直接将页面处理为静态的HTML文件

在Next.js中使用静态站点生成:

1.页面是静态的不依赖其他数据: 打包时直接生成静态文件不需要额外处理

function About() {
  return <div>About</div>
}
 
export default About

2.页面内容需要用到请求的数据,比如获取文章内容:
使用getStaticProps :

  • 在组件文件中暴露一个async函数getStaticProps,该函数会在打包构建时被调用,请求数据
  • getStaticProps获取的数据通过props传递给Page组件
export default function Blog({ posts }) {
}
 
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // By returning { props: { posts } }, the Blog component
  return {
    props: {
      posts,
    },
  }
}

3.页面路径需要用到请求的数据,在Next.js中存在动态路由,比如文章页面:article/[id]/...,id并不是固定的Nextjs中需要使用getStaticPaths去定义预渲染的路径。

// 这个函数在 build 时会调用
export async function getStaticPaths() {
  // 请求 API 获取数据
  const res = await fetch('https://.../posts')
  const posts = await res.json()
​
  // 基于 posts 获取我们想要预渲染的路径
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
​
  // 在 build 时我们只会预渲染 paths 数组中的路径
  return { paths, fallback: false }
}

在暴露getStaticProps的基础上再暴露一个getStaticPaths函数。函数会在构建打包时被调用,path包含了需要预渲染的路径,
fallback则决定了当访问到的是没有被预渲染包含的路径时需要如何处理:

  • false:按404处理;
  • tru:在第一次请求的过程中使用SSR获取对应的数据并返回并缓存html;
  • blocking: 和true同样的处理方式,不过true时进入页面和getStaticProps是同时进行的,相当于异步而,blocking则是等到getStaticProps返回数据后再进入页面。

ISR:静态增量生成(Incremental Static Regeneration)

在某些情况下,页面的大部分内容在打开之后是不会变化的,但是少部分内容需要动态更新
在使用SSG的情况下,再通过重新构建更新内容是不现实的。
ISR可以只生成部分需要更新的页面
在第一次构建时所有页面的静态页面会被生成,当内容更新时,ISR会在服务端重新生成新页面并缓存,并在下一次请求过程中替换旧页面。

在Nextjs中使用静态增量生成:
只需在SSG配置的基础上:getStaticProps中配置revalidate,单位为秒,为页面更新间隔。

function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
 
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  return {
    props: {
      posts,
    },
    revalidate: 10,  
    }
}
 

export async function getStaticPaths() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
 
  return { paths, fallback: 'blocking' }
}
 
export default Blog

revalidate被设为10时,在10s之内访问页面都会显示旧的HTML页面,当10s时间后发生了一次请求,旧页面仍旧会被使用,但是此时Next.jss会开始重新处理生成新的HTML页面,并在下次请求后返回新的HTML页面。


在Next.js中这些渲染方式可以组合使用,从而实现更好的用户体验。

原文链接:https://juejin.cn/post/7357922389415460873 作者:Lumen丶

(0)
上一篇 2024年4月16日 上午10:26
下一篇 2024年4月16日 上午10:36

相关推荐

发表回复

登录后才能评论