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

相关推荐
总要学点什么9 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技9 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥9 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易10 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭10 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter
严肃小白兔11 小时前
TanStack Router 更新构建工具链:Node.js 兼容性、路由分割与前端工程实践
前端·node.js·状态模式
IT_陈寒11 小时前
Vue这个奇葩的响应式问题让我加班到凌晨
前端·人工智能·后端
风骏时光牛马12 小时前
功能可用性自动化测试验证
前端
LucianaiB21 小时前
【元宝搜索开发者征文大赛】AI时代,学得慢就不用学?用元宝搜索打造一个教程保质期,确保每一个教程符合你的现状
前端·人工智能·ai编程
excel1 天前
JavaScript 对象池:减少高频对象创建与 GC 压力
前端