⚡️ 聊一聊Nextjs的渲染策略,以及如何选择合适的渲染策略

渲染策略分类

SSR:Server-Side Rendering,服务器端渲染;

SSG :Server-Static Generation,服务端静态生成,也叫编译生成

ISR :Incremental Static Regeneration 静态增量生成

CSR:Client-Side Rendering,客户端渲染

默认情况,Next.js 会预渲染每个页面。这意味着 Next.js 会将网站的所有页面提前生成静态 HTML 文件并保存下来。当用户访问网站时,服务器会返回预渲染好的静态 HTML 文件,而不是使用 JavaScript 动态生成网页内容。
在直接使用 Vue 或者 React 时,页面的渲染是完全由 JS 执行的,在 JS 未渲染完成前,页面中可能只有类似 <div id='root'></div> 的一个容器标签,当 JavaScript 文件被加载并执行时,它们会根据代码逻辑和数据来生成最终的 HTML 标记和页面内容,并将其插入到页面中的容器标签中。

在 Next.js 中想要使用某种渲染方式,例如我想指定 SSR 或是 SSG,并不是说直接在某个配置文件中改一个配置就可以的,而是我们在页面中使用了一些相关的 API,而 Next.js 在打包时检测到了才会进行相应的页面构建策略。

渲染效果对比

在 Next.js 中,预渲染(Pre-rendering)和非预渲染(Non-pre-rendering)是两种不同的页面渲染方式

  1. 预渲染是指在构建时或请求时生成 HTML 页面,并在客户端请求时直接返回生成的 HTML。预渲染可以提高页面加载速度和 SEO 性能。即SSG、SSR。

  2. 非预渲染是指在客户端渲染页面内容。这意味着 HTML 页面在客户端生成,而不是在构建时或请求时生成。适用于需要在客户端动态生成内容的页面。即CSR。

静态网站生成(SSG)

Next’s 中静态网站生成一般分为三种情况,分别是

  1. 纯静态页面,不需要依赖外部数据
  2. 页面的 内容 依赖外部数据
  3. 页面的 路径 依赖外部数据
不需要依赖外部数据
function About() {return <div>About</div>
}export default About

这种情况最简单,Next.js 会在打包时直接生成一个静态的 HTML。

页面的内容依赖外部数据
export default function Blog({ posts }) {// 渲染文章...
}// 这个函数会在 build 时接收请求
export async function getStaticProps() {// 请求 API 获取文章数据const res = await fetch('https://.../posts')const posts = await res.json()// 在构建时,Blog 组件可以接收到 posts 这个 propsreturn {props: {posts,},}
}

为了能够在预渲染的时候拿到外部的数据,可以在定义组件的那个文件中暴露一个异步函数 getStaticProps ,在打包页面时 Next.js 会先执行 getStaticProps 中的操作,例如发送请求,数据处理之类的。

然后可以返回一个对象,其中 props 字段的值会在渲染组件时作为 props 传入,这样就实现了构建时从外部获取数据。

页面的路径依赖外部数据

Next.js 的路由是由文件系统驱动的,每个页面都对应着一个文件,这个文件的路径就是这个页面的路由路径。例如,pages/index.js 对应着根路径 /,而 pages/about.js 对应着 /about 路径。

当然不是所有的页面都是固定路由的,而动态路由就是一种可以基于 URL 参数动态生成页面的路由。例如,你可以创建一个 /posts/[id] 的页面路由,用于显示具有不同 id 值的文章详情页面。

而如果我们使用了动态路由,例如前面提到的文章 id ,那么 Next.js 如何得到我们有哪些文章 id 以实现预渲染呢?

// 这个函数在 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 数组中的路径// { fallback: false } 意为其他的路由都会返回 404return { paths, fallback: false }
}

可以在定义组件的那个文件中再暴露一个异步函数 getStaticPaths ,这个函数可以返回一个包含 pathsfallback 属性的对象,paths 是一个包含了所有动态路由路径的数组,它决定了哪些路径将被预渲染。而 fallback 则表示访问还没有生成 html 的路径时,要采取怎么样的策略,它存在三种情况

  • false:访问任何在 getStaticPaths() 函数中未返回的路径都会响应 404 页面。
  • true:build 时未生成的路径不会返回 404 页面。而是在第一次请求时进行 SSR 并返回生成的 HTML。这个生成的 HTML 会被缓存,也就是说你访问这个路径时,即便对应的数据已经更新了还是会返回原本的页面,直到缓存过期重新生成 HTML。
  • 'blocking''blocking' 策略与设置为 true 时相同,不同点在于设置为 true 时,我们会直接进入访问的路径,并同时执行 getStaticProps ,并且可以通过 router.isFallback 判断getStaticProps 是否已经执行完成,而 'blocking' 策略则会先执行 getStaticProps ,直到执行完成才会进入新的页面。也就是同步与异步的关系。

虽然预渲染这么方便,将我的每个页面都生成静态文件了,那如果页面更新了怎么办呢?难道我需要执行 build 重新生成所有页面嘛?这里就需要引入 ISR 的概念了。

静态增量生成(ISR)

ISR(Incremental Static Regeneration) 是一种在静态站点生成过程中,增量更新部分页面的技术。传统的静态网站生成方式需要每次完全重新生成全部页面,这在网站内容变化频繁的情况下可能会导致生成时间较长,同时也可能会降低网站的性能。

ISR 的思想是只 重新生成需要更新部分页面。这样可以显著减少生成时间和资源占用,并且能够提高网站的响应速度。当用户请求一个需要更新的页面时,ISR 会在后台自动重新生成该页面,然后将其缓存,以便下一次请求时可以快速响应。

要在 Next.js 中开启 ISR ,只需要在前面介绍的 getStaticProps 函数中返回一个 revalidate 属性,下面放一个官方的示例:

function Blog({ posts }) {return (<ul>{posts.map((post) => (<li key={post.id}>{post.title}</li>))}</ul>)
}// 这个方法会在服务端渲染或者 build 时被调用
// 当使用了 serverless 函数、开启 revalidate 并且接受到新的请求时也会被重新调用
export async function getStaticProps() {const res = await fetch('https://.../posts')const posts = await res.json()return {props: {posts,},// Next 将会尝试重新生成页面:// - 接受到新的请求// - 每隔最多十秒钟revalidate: 10, // 单位为秒}
}// 这个方法会在服务端渲染或者 build 时被调用
// 当该路径还没有被生成过就会被重新调用
export async function getStaticPaths() {const res = await fetch('https://.../posts')const posts = await res.json()// 基于 posts 获取我们想要预渲染的路径const paths = posts.map((post) => ({params: { id: post.id },}))// 在 build 时,我们将只预渲染 paths 中的路径// { fallback: 'blocking' } 在页面不存在时按需进行服务端渲染。return { paths, fallback: 'blocking' }
}export default Blog

ISR 的实现方式是将某些页面标记为可 ISR 页面。这些页面在生成时与 SSG 页面相同,但它们还有一个“revalidate”(再生成时间) 。这个时间告诉 Next.js 何时需要重新生成页面。

例如,假设我们需要构建一个新闻网站,希望能在首页上显示最新的新闻文章。在 Next.js 中,我们就可以将首页标记为 ISR 页面,并设置重新生成时间为 10 秒钟。这意味着,Next.js 将在访问首页时,返回上一次生成的静态页面,同时在后台开始重新生成新的页面。10 秒后,当新页面生成完毕后,Next.js 会将新页面替换旧页面,并提供给用户。

服务端渲染 (SSR)

在 Next.js 中,如果启用了 SSR,那么每次的每次请求都会重新生成页面。想要开启 SSR,我们可以在定义组件的那个文件中暴露一个异步函数 getServerSideProps,这个方法类似于 getStaticProps ,只是执行的时机不同, getServerSideProps 会在每次页面接受请求时都调用。

export default function Page({ data }) {// 渲染数据...
}// 这个方法每次请求时都会调用
export async function getServerSideProps() {// 从外部 API 获取数据const res = await fetch(`https://.../data`)const data = await res.json()// 通过 props 向组件内传入数据return { props: { data } }
}

除了调用时机外,getServerSidePropsgetStaticProps 并无二致。

客户端渲染 (CSR)

可以使用 Next.js 的 客户端渲染 + next export 实现。

在 Next.js 中想要使用客户端渲染也很简单,只要上述的这些 API ,例如 getStaticPropsgetServerSideProps 都没有使用,数据都是通过在组件内部使用 axios 或者 fetch 去发送请求获取并渲染的,那么我们使用的就是纯客户端渲染了,与直接使用 Vue 或 React 并无二致。

但即便你的每一个页面都是使用的客户端渲染,在执行 build 时,Next.js 还是会为你打包成一个需要持续运行的 Node.js 服务,而不是直接打包为一个静态文件。

想要导出为静态文件,需要使用单独的打包方式,那就是静态 HTML 导出。

静态 HTML 导出

Next.js 可用于生成静态应用程序,可以实现在浏览器中使用 React 而无需 Node.js 服务器。就可以使用 next export 命令去将你的站点构建为一个静态的文件。

首先更新 next.config.js 中的 outputexport :

/*** @type {import('next').NextConfig}*/
const nextConfig = {output: 'export',
}
​
module.exports = nextConfig

然后更新 package.jsonbuild 指令以包含 next export

"scripts": {"build": "next build && next export"
}

运行 npm run build 会生成一个 out 目录。

如何选择渲染方式

选择客户端渲染(CSR)的场景:
  1. 交互式用户体验:如果你的应用需要高度交互式的用户体验,比如单页应用程序(SPA)那样的即时反馈和流畅的界面切换,CSR 是一个很好的选择。它允许在不重新加载整个页面的情况下动态更新内容,提升了用户体验。
  2. 动态数据需求:当应用中的大部分内容依赖于用户操作或实时更新时(如聊天应用、仪表盘、个性化内容展示),CSR 能更高效地处理这些需求,因为它可以直接在客户端根据用户行为或API响应来更新页面。
  3. 减少服务器负担:CSR将渲染工作转移到了客户端,这意味着服务器只需提供初始的HTML文档和必要的数据API,减少了服务器的CPU和内存消耗,尤其适合流量较大的应用。
  4. 初始加载时间容忍度:如果用户群体对首次页面加载时间有较高容忍度,或者可以通过骨架屏、懒加载等技术缓解等待感,那么可以选择CSR。因为相比SSR,CSR在首次加载时可能需要更长时间来下载JavaScript bundle并执行渲染。
  5. SEO非关键或已有解决方案:如果SEO不是项目的主要关注点,或者已经有解决方案可以弥补CSR在SEO上的不足(例如使用预渲染、动态渲染服务),则可以偏向于选择CSR。
选择服务器端渲染(SSR)的场景:
  1. SEO优化:对于依赖搜索引擎流量的内容驱动型网站,如新闻门户、博客、电商产品列表等,SSR至关重要。搜索引擎爬虫通常更偏好服务器端渲染的页面,因为它们可以直接抓取到完整渲染的HTML内容,有助于提升搜索引擎排名。
  2. 首屏加载速度:在慢速网络环境下或对首屏加载时间有严格要求的应用中,SSR可以提供即时的、可交互的初始页面内容,无需等待JavaScript下载和执行,从而改善用户体验。
  3. 减少客户端负担:对于低端设备或资源受限的客户端,SSR可以减轻其计算负担,因为大部分渲染工作在服务器完成,客户端只需处理交互逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1489025.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

福特汽车:总是悲喜交加时

每辆电动汽车的亏损高达6.94万美元&#xff0c;这把全美最大汽车制造商——福特汽车&#xff0c;也整不会了。 燃油车全美销量第一、电动车全美销量第二&#xff0c;销量大增的福特汽车增收不增利&#xff0c;息税前利润下滑27%至28亿美元&#xff0c; 因盈利远不及预期&#x…

【Python】pandas:查看数据(head, tail, values属性, at, iat, loc, iloc, [ ], sample)

pandas是Python的扩展库&#xff08;第三方库&#xff09;&#xff0c;为Python编程语言提供 高性能、易于使用的数据结构和数据分析工具。 pandas官方文档&#xff1a;User Guide — pandas 2.2.2 documentation (pydata.org) 帮助&#xff1a;可使用help(...)查看函数说明文…

Spring Boot:图书管理系统(一)

1.编写用户登录接口 代码&#xff1a; package com.example.demo;import jakarta.servlet.http.HttpSession; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotatio…

Linux 查找命令

目录 1. 查看二进制文件 which 2. 查看指定文件 find ​2.1 文件名查找 2.2 文件大小查找 前面学习过的 Linux 命令&#xff0c;其实质是一个个的二进制可执行程序&#xff0c;与 Windows 系统中的 .exe 文件是一个意思。 1. 查看二进制文件 which 语法&#xff1a; w…

sonar代码扫描报错:ERROR: Something went wrong storing the PDF at server side.

原因&#xff1a; URL带“/”引起的&#xff0c;去掉即可。 去掉之后成功&#xff1a;

2、从0搭建企业门户网站——云服务器租用

目录 正文 1、登录阿里云 2、进入云服务器界面 3、租用云服务器 正文 云服务器厂商很多,这里主要以阿里云服务器为主介绍云服务器的相关知识。 1、登录阿里云 阿里云官网地址 2、进入云服务器界面 登录后,点击控制台,进入主界面。

当AI遇上“近亲繁殖”:牛津剑桥Nature封面揭秘

在这个AI无所不能的时代,一项新的研究再次刷新了我们的认知边界。牛津大学、剑桥大学、帝国理工学院和多伦多大学的研究团队,携手登上《自然》杂志封面,揭露了一个令人震惊的事实:AI也可能遭遇“近亲繁殖”的问题! 更多信息,请关注微信公众号:JAVA和人工智能 “近亲繁…

[Unity] ShaderGraph实现不同贴图素材的同一材质球复用

无意间发现的ShaderGraph小技巧&#xff0c; 可以实现同一个ShaderGraph&#xff0c;同一个Material材质球&#xff0c; 但使用不同的Texture贴图&#xff0c;而Sprite显示不会相互覆盖。 具体实现方法如下&#xff1a; 声明Texture2D时&#xff0c;把名字命名成&#xff1a…

github-page静态网页将字符串写入github库中文本文档

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

echarts使用案例

1.配置legend icon 根据点击事件动态更换样式 <template><div ref"chart" style"width: 600px; height: 400px;"></div></template><script>import * as echarts from echarts;export default {name: EchartsExample,data(…

Canvas生成动画---显示一组彩色气泡

一、JS版本 <!--* Author: LYM* Date: 2024-07-26 13:51:47* LastEditors: LYM* LastEditTime: 2024-07-26 16:14:40* Description: Please set Description --> <!DOCTYPE html> <html> <head><title>canvas动态气泡</title><style&g…

JMeter接口测试:测试中奖概率!

介绍 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试领域&#xff0c;可用于测试静态和动态资源&#xff0c;如静态文件、Java 小服务程序、CGI 脚本、J…

学习日志:JVM垃圾回收

文章目录 前言一、堆空间的基本结构二、内存分配和回收原则对象优先在 Eden 区分配大对象直接进入老年代长期存活的对象将进入老年代主要进行 gc 的区域空间分配担保 三、死亡对象判断方法引用计数法可达性分析算法引用类型总结1&#xff0e;强引用&#xff08;StrongReference…

联想教育电脑硬盘保护同传EDU系统使用简明教程

目录 一、原理概述 二、简明使用方法 1、软件下载 2、开机引导 3、开始安装 4、使用 &#xff08;1&#xff09;进入底层 &#xff08;2&#xff09;进行分区设置 &#xff08;3&#xff09;系统设置 &#xff08;4&#xff09;安装硬盘保护驱动 &#xff08;5&…

VUE3学习第三篇:报错记录

1、在我整理好前端代码框架后&#xff0c;而且也启动好了对应的后台服务&#xff0c;访问页面&#xff0c;正常。 2、报错ReferenceError: defineModel is not defined 学到这里报错了 在vue网站的演练场&#xff0c;使用没问题 但是在我自己的代码里就出问题了 3、watchEffec…

【YOLOv5/v7改进系列】引入中心化特征金字塔的EVC模块

一、导言 现有的特征金字塔方法过于关注层间特征交互而忽视了层内特征的调控。尽管有些方法尝试通过注意力机制或视觉变换器来学习紧凑的层内特征表示&#xff0c;但这些方法往往忽略了对密集预测任务非常重要的被忽视的角落区域。 为了解决这个问题&#xff0c;作者提出了CF…

算法与算法分析

目录 一.前言 二.算法的特性和要求 三.分析算法--时间效率 四. 分析算法--空间效率 一.前言 算法就是对特定问题求解方法和步骤的一种描述&#xff0c;它是指令的有限序列。其中&#xff0c;每个指令表示一个或多个操作。总而言之&#xff0c;我们数据结构就是通过算法实现操…

微信小程序之调查问卷

一、设计思路 1、界面 调查问卷又称调查表&#xff0c;是以问题的形式系统地记载调查内容的一种形式。微信小程序制作的调查问卷&#xff0c;可以在短时间内快速收集反馈信息。具体效果如下所示&#xff1a; 2、思路 此调查问卷采用服务器客户端的方式进行设计&#xff0c;服…

力扣141环形链表问题|快慢指针算法详细推理,判断链表是否有环|龟兔赛跑算法

做题链接 目录 前言&#xff1a; 一、算法推导&#xff1a; 1.假设有环并且一定会相遇&#xff0c;那么一定是在环内相遇&#xff0c;且是快指针追上慢指针。 2.有环就一定会相遇吗&#xff1f;快指针是每次跳两步&#xff0c;有没有可能把慢指针跳过去&#xff1f; 3.那一定…

大模型算法备案流程最详细说明【流程+附件】

文章目录 一、语料安全评估 二、黑盒测试 三、模型安全措施评估 四、性能评估 五、性能评估 六、安全性评估 七、可解释性评估 八、法律和合规性评估 九、应急管理措施 十、材料准备 十一、【线下流程】大模型备案线下详细步骤说明 十二、【线上流程】算法备案填报…