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

相关推荐
Dragon Wu1 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym6 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫7 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫11 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat13 分钟前
前端性能优化2
前端
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
会发光的猪。2 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
我要洋人死3 小时前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人3 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome