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 等去获取;
js 复制代码
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组件;

js 复制代码
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.页面是静态的不依赖其他数据: 打包时直接生成静态文件不需要额外处理

js 复制代码
function About() {
  return <div>About</div>
}
 
export default About

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

使用getStaticProps :

  • 在组件文件中暴露一个async函数getStaticProps,该函数会在打包构建时被调用,请求数据
  • getStaticProps获取的数据通过props传递给Page组件
js 复制代码
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去定义预渲染的路径。

js 复制代码
// 这个函数在 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,单位为秒,为页面更新间隔。

js 复制代码
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中这些渲染方式可以组合使用,从而实现更好的用户体验。

相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者7 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794488 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存