当前位置: 首页 > news >正文

React进阶之React核心源码解析(一)

React核心源码解析

  • react 特点
    • CPU卡顿
    • IO 卡顿
  • 新老 react 架构对比
    • v15
    • v16.8
      • Scheduler 调度器
      • Reconciler 协调器
  • React fiber
    • 原理
    • 更新dom
    • mount 构建过程
  • render阶段 — scheduler reconciler
  • react源码解析
    • react-dom
      • react-dom/src/client/ReactDOMRoot.js
    • react-reconciler
      • react-reconciler/src/ReactFiberReconciler.js
      • react-reconciler/src/ReactFiberWorkLoop.js
      • react-reconciler/src/ReactFiberBeginWork.js
      • react-reconciler/src/ReactChildFiber.js
      • react-reconciler/src/ReactFiber.js
      • react-reconciler/src/ReactFiberWorkLoop.js
  • commit阶段 同步阶段

cline + deeseek => AI工具,上手成本非常低,非常便宜
cursor 编辑器

带着问题学源码

  1. 为什么 react 会引入 fiber 架构
  2. 简述 fiber 节点的结构和作用
  3. fiber 架构 => 架构+流程
  4. diff 算法
  5. hooks 原理

学习方法论:由大到小 对比回答问题

react 特点

  1. 单向数据流
    能够快速响应用户操作
    公式:ui = render(data)

什么原因导致响应慢?
cpu卡顿,js执行导致画面卡顿
IO卡顿,网络问题等 延迟

CPU卡顿

浏览器一秒60hz,16.6ms刷新一次,超过就会有掉帧现象
就比如这个例子

// index.js
import ReactDOM from "react-dom";import App from "./App";const rootElement = document.getElementById("root");// ReactDOM.render(<App />, rootElement);
ReactDOM.createRoot(rootElement).render(<App />);// APP.js
import "./styles.css";export default function App() {const len = 3000;return (<ul>{Array(len).fill(0).map((_, i) => (<li>{i}</li>))}</ul>);
}

React是怎么解决的?
时间分片:把更新过程碎片化 优先级 应用更新 后台预渲染

  • 同步 阻塞 渲染
  • 异步 非阻塞 用户优先级渲染

16.8后提出的 concurrent mode

ReactDOM.createRoot(rootEl).render(<App />)

IO 卡顿

接口响应时间长,解决:

  • loading
  • suspence 兜底 fallback
  • error-boundary 错误兜底
    在这里插入图片描述

新老 react 架构对比

v15 同步的,不可中断的
v16.8 异步,可中断
v18 ssr升级 流式 ssr stream,针对页面所有组件是分块,分局部输出,而不是等所有页面拼接组装好后一次性传输给客户端
页面上的不同接口,包裹成流式,然后传输给客户端,提升TTFB(首字节响应时间)
性能优化有需求,使用nextjs做提升

v15

  • Reconciler 协调器,diff 负责找出变化的组件
    • update 更新
    • component render jsx 渲染 => vdom
    • vdom diff
    • 找出变化的元素
    • 通知 renderer 渲染

通过递归的方式找出变化的组件
mount 阶段 => 调用 mountComponent
update 阶段 => 调用 updateComponent

递归更新子组件
=> 缺点:层级深,递归时间超过16ms

  • Renderer 渲染器,负责将变化的组件渲染到页面上
    • ReactDom.render
    • ReactNative.render

不可中断,中断则后续内容不执行

v16.8

多了一个 Scheduler 调度器

  • Scheduler 调度器 调度任务的优先级
  • Reconciler 协调器 负责找出变化的组件 递归=>可中断
  • Renderer 渲染器 是拿着Reconciler提供的标识 同步渲染

Scheduler 调度器

将大型任务分割成小任务,每一帧分配一定的时间执行小任务

  • 时间切片
  • 优先级调度
  1. 每个工作单元,对应一个fiber节点
  2. 时间分配
  3. 调度循环 维护任务队列
  4. 时间检查
  5. 暂停与恢复
  6. 利用浏览器API
  • requestAnimationFrame 用于在下一帧开始的时候执行回调函数
  • requestIdleCallBack 浏览器空闲的时候执行回调函数 setTimeout 模拟了

Reconciler 协调器

// 更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield判断当前是否有剩余时间。/** @noinline */
function workLoopConcurrent() {// Perform work until Scheduler asks us to yieldwhile (workInProgress !== null && !shouldYield()) {workInProgress = performUnitOfWork(workInProgress);}
}

React fiber

原理

react 内部实现的数据结构,支持状态更新,可中断可恢复,恢复后可以复用之前的中间状态

  • 架构:v15 stack reconciler,v16 fiber reconciler
  • 数据结构:每个 fiber 节点对应 react element,多个组件类型,dom节点各种属性数据
  • 动态的工作单元,改变的状态,要执行的工作
function FiberNode(tag: WorkTag,pendingProps: mixed,key: null | string,mode: TypeOfMode,
) {// Instance,静态节点的数据结构属性this.tag = tag;this.key = key;this.elementType = null;this.type = null;this.stateNode = null;// Fiber,用来链接其他fiber节点形成的fiber树this.return = null;this.child = null;this.sibling = null;this.index = 0;this.ref = null;// 作为动态的工作单元的属性this.pendingProps = pendingProps; //即将应用到组件上新属性 相当于是新值newValue this.memoizedProps = null; // 上次渲染时使用的属性值 相当于是旧值oldValuethis.updateQueue = null;this.memoizedState = null;this.dependencies = null;this.mode = mode;// 记录变化的节点 effectlist=>renderthis.effectTag = NoEffect;this.subtreeTag = NoSubtreeEffect;this.deletions = null;this.nextEffect = null;// effectslist链 = firstEffect -> nextEffect -> nextEffect -> lastEffect => 交给render => 渲染this.firstEffect = null;this.lastEffect = null;// 作为调度优先级的属性this.lanes = NoLanes;this.childLanes = NoLanes;// 指向该fiber在另一次更新时对应的fiberthis.alternate = null;if (enableProfilerTimer) {// Note: The following is done to avoid a v8 performance cliff.//// Initializing the fields below to smis and later updating them with// double values will cause Fibers to end up having separate shapes.// This behavior/bug has something to do with Object.preventExtension().// Fortunately this only impacts DEV builds.// Unfortunately it makes React unusably slow for some applications.// To work around this, initialize the fields below with doubles.//// Learn more about this here:// https://github.com/facebook/react/issues/14365// https://bugs.chromium.org/p/v8/issues/detail?id=8538this.actualDuration = Number.NaN;this.actualStartTime = Number.NaN;this.selfBaseDuration = Number.NaN;this.treeBaseDuration = Number.NaN;// It's okay to replace the initial doubles with smis after initialization.// This won't trigger the performance cliff mentioned above,// and it simplifies other profiler code (including DevTools).this.actualDuration = 0;this.actualStartTime = -1;this.selfBaseDuration = 0;this.treeBaseDuration = 0;}if (__DEV__) {// This isn't directly used but is handy for debugging internals:this._debugID = debugCounter++;this._debugSource = null;this._debugOwner = null;this._debugNeedsRemount = false;this._debugHookTypes = null;if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {Object.preventExtensions(this);}}
}

在这里插入图片描述
举个例子:

import React, { Component } from 'react';class Header extends Component {render() {return <h1>{this.props.title}</h1>;}
}function Content(props) {return (<div><p>{props.text}</p><Footer /></div>);
}class Footer extends Component {render() {return <footer>Footer Content</footer>;}
}class App extends Component {render() {return (<div><Header title="Welcome to My App" /><Content text="This is some example content." /></div>);}
}export default App;

Fiber结构:
Root Fiber Node
└── Type: “div” (elementType: “div”)
├── Child Fiber Node
│ ├── Type: “Header” (elementType: Header)
│ │ └── State Node: Header instance
│ │ └── Props: { title: “Welcome to My App” }
│ └── Sibling: Content Fiber Node
└── Child Fiber Node
├── Type: “Content” (elementType: Content)
│ └── State Node: null (函数组件没有状态节点)
│ └── Props: { text: “This is some example content.” }
│ └── Child Fiber Node
│ ├── Type: “Footer” (elementType: Footer)
│ │ └── State Node: Footer instance
│ │ └── Props: {}
│ └── Sibling: null

更新dom

双缓存机制
内存中绘制当前的 fiber dom,绘制完后直接替换上一帧的fiber dom,这样省去两帧之间替换的计算时间,就不会存在白屏的情况,因此就有两棵fiber树

  • current fiber 屏幕上正在显示的内容
  • workingprogress fiber 内存中正在构建的树 简称 wip fiber

alternate 连接

在这里插入图片描述
在这里插入图片描述

mount 构建过程

  • 应用级别的节点 ReactDom.render 创建 fiberRootNode
  • rootFiber 组件树的根节点

在这里插入图片描述

render阶段 — scheduler reconciler

通过遍历 找到所有的fiber结构 实现可中断的异步递归

  1. 递 => 生成树
    创建节点,形成节点之间的关系
    vdom

从 rootfiber 深度优先遍历 fiber 调用 beginwork

  • 根据传入的 fiber 节点创建子 fiber 节点,连接两个 fiber 节点
  • 遍历叶子节点,进入归的阶段

  1. 调用completework
  • 创建真实的dom节点
  • 将当前节点下的子节点挂载到当前节点上
  • 收集当前节点的effectlist

递 归 交错执行,直到归到rootFiber
在这里插入图片描述

react源码解析

react github

react-dom

在这里插入图片描述

react-dom/src/client/ReactDOMRoot.js

在这里插入图片描述
在这里插入图片描述
最终返回ReactDOMRoot这个实例

ReactDOMRoot 和 ReactDOMHydrationRoot 上面都挂载 render 方法
接收children
调用updateContainer方法,传入children,updateContainer来进行递归的这个阶段,创建当前节点
在这里插入图片描述

后面还挂载了unmount方法
在这里插入图片描述

react-reconciler

react-reconciler/src/ReactFiberReconciler.js

这里着重是 Scheduler
创建FiberRootNode节点绑定root
render渲染方法传入children(App),调用updateContainer方法,进行大任务拆分小任务,优先级调度
在这里插入图片描述

react-reconciler/src/ReactFiberWorkLoop.js

着重介绍循环创建fiber树的方法
核心方法:performUnitOfWork,workLoopConcurrent
workLoopSync 同步方法,不会判断 shouldYield,这是和workLoopConcurrent方法的区别
在这里插入图片描述
workLoopConcurrent方法是异步模式,都是调用performUnitOfWork构造fiber树
在这里插入图片描述
这里是Scheduler调度器将渲染任务拆分成不同的任务单元去创建对应的fiber,fiber通过performUnitOfWork去完成fiber单元的创建,然后通过shouldYield判断是否执行这样的任务
workInProgress是全局的变量,存储在全局

performUnitOfWork中记录当前“递”和“归”的一个过程,判断当前满足条件,进入beginWork

Reconciler 协调器阶段,创建fiber树,递归遍历,diff算法比较差异
performUnitOfWork中判断是否是开发环境,开发环境开启性能调优则计算执行时间
调用beginWork进行节点的递阶段,拆解组件内容,并且返回下一个组件
当深度遍历到最底层的时候,开始进行归的阶段
则next为空,调用completeUnitOfWork开始”归“的阶段,归回父节点,更新父节点状态
"递"和"归"阶段是交错执行的,直到回到rootFiber为止
在这里插入图片描述

react-reconciler/src/ReactFiberBeginWork.js

  1. beginWork
    在这里插入图片描述
    if 阶段:后续进入到diff的过程,非首次渲染
    否则为else阶段

后面:
在这里插入图片描述

  1. updateHostComponent
    在这里插入图片描述

  2. reconcileChildren
    mount组件:创建新的子Fiber节点
    在这里插入图片描述

react-reconciler/src/ReactChildFiber.js

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
通过调用useFiber创建fiber节点
在这里插入图片描述

react-reconciler/src/ReactFiber.js

找到workInProgress,为null则创建Fiber节点
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
不论是哪个方法,最终返回的都是 workInProgress.child下一个节点

react-reconciler/src/ReactFiberWorkLoop.js

performUnitOfWork中
上述 beginWork返回的是workInProgress.child下一个节点,因此next就会发生变化
next为null时候,则叶子节点为空,调用completeUnitOfWork
在这里插入图片描述
next不为空,则将next指针赋值给workInProgress,修改workInProgress指向,重新执行beginWork

在 completeUnitOfWork 中,创建对应的dom元素,如果sibling不为null,然后创建对应的指针
在这里插入图片描述

commit阶段 同步阶段

effectlist

  • before mutation 阶段,执行 dom操作前
  • mutation 阶段,执行dom操作阶段,遍历effectlist,执行mutation
  • layout 阶段,执行dom操作后,绘制

可以自己写一个实例,然后打断点看操作数据,操作结果
在这里插入图片描述

一句话来总结commit阶段所作的事情:
基于链表的方式存储副作用,并根据优先级执行这些更新,直至所有的更新完成。

  1. React遍历fiber树并将需要执行副作用的节点以链表的形式收集起来
  2. 根据优先级存储更新
  3. 递归执行更新

相关文章:

React进阶之React核心源码解析(一)

React核心源码解析 react 特点CPU卡顿IO 卡顿 新老 react 架构对比v15v16.8Scheduler 调度器Reconciler 协调器 React fiber原理更新dommount 构建过程 render阶段 — scheduler reconcilerreact源码解析react-domreact-dom/src/client/ReactDOMRoot.js react-reconcilerreact-…...

用大模型学大模型03-数学基础 概率论 条件概率 全概率公式 贝叶斯定理

要深入浅出地理解条件概率与贝叶斯定理&#xff0c;可以从以下几个方面入手&#xff0c;结合理论知识和实例进行学习&#xff1a; 贝叶斯定理与智能世界的暗语 条件概率&#xff0c;全概率公式与贝叶斯公式的推导&#xff0c;理解和应用 拉普拉斯平滑 贝叶斯解决垃圾邮件分类 …...

C++ Primer 参数传递

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…...

Jupyter lab 无法导出格式 Save and Export Notebook As无法展开

本来尝试jypyter lab如何导出HTML带有侧边导航栏&#xff0c;一顿操作后发现还是没实现。 又突然发现导出其他格式地功能不能用了&#xff0c;浏览器里Save and Export Notebook As展开按钮为灰色打不开。 经典想实现的没实现还把原先的搞坏了。 看了jupyter lab的运行信息发…...

Mac之JDK安装

Mac之JDK安装 一.安装 jdk 打开终端输入命令:java -version 查看是否已安装 JDK Oracle 官方下载地址 根据自己Mac 系统安装 查看 Mac 系统&#xff0c;打开中断命令&#xff0c;输入: uname -a Compressed Archive 是压缩文档&#xff0c;下载的是一个 .tar.gz 压缩包 D…...

OpenEuler学习笔记(三十一):在OpenEuler上搭建仓颉语言开发环境

仓颉语言&#xff08;Cangjie programming language&#xff09;相对较为小众&#xff0c;截至2025年&#xff0c;并没有广泛的资料和成熟的通用搭建流程。不过下面为你提供一个较为通用的在OpenEuler上搭建开发环境的大致思路&#xff0c;你可以根据实际情况进行调整。 1. 安…...

2021年全国研究生数学建模竞赛华为杯E题信号干扰下的超宽带(UWB)精确定位问题求解全过程文档及程序

2021年全国研究生数学建模竞赛华为杯 E题 信号干扰下的超宽带(UWB)精确定位问题 原题再现&#xff1a; 一、背景   UWB&#xff08;Ultra-Wideband&#xff09;技术也被称之为“超宽带”&#xff0c;又称之为脉冲无线电技术。这是一种无需任何载波&#xff0c;通过发送纳秒…...

【电脑】u盘重装win7

u盘必须8GB以上 1. CPU型号 首先查看CPU的型号看看到底能不能装win7 2. 下载光盘映像文件 网址 看电脑是多少位的机器(32位下载x86 64位下载x64) 一共是这么多个版本按需下载对应的版本 电脑小白推荐无脑下载旗舰版 将链接复制到迅雷进行下载 3. 下载软碟通 网址 下…...

HCIA项目实践--RIP的拓展配置

9.4.7 RIP的拓展配置 &#xff08;1&#xff09;RIPV2的手工认证 RIPv2 的手工认证是增强网络安全性的手段。管理员手动配置密钥&#xff0c;路由器在收发 RIPv2 路由更新消息时&#xff0c;会对消息中的认证信息进行检查。发送方添加密钥&#xff0c;接收方用预设密钥验证。若…...

常用架构图:业务架构、产品架构、系统架构、数据架构、技术架构、应用架构、功能架构及信息架构

文章目录 引言常见的架构图I 业务架构图-案例模块功能说明1. 用户界面层 (UI)2. 应用服务层3. 数据管理层4. 基础设施层业务流程图示例技术实现II 功能架构图 -案例功能模块说明1. 船舶监控模块2. 报警管理模块3. 应急响应模块4. 通信管理模块5. 数据分析模块数据管理层基础设施…...

初阶c语言(练习题,猜随机数,关机程序)

目录 第一题&#xff0c;使用函数编写一个随机数&#xff0c;然后自己猜&#xff0c;猜随机数 第二道题&#xff08;关机程序&#xff09; 实现代码&#xff08;关机程序&#xff09; 实现代码&#xff08;猜数字&#xff09; 前言&#xff1a; 学习c语言&#xff0c;学习…...

三维重建(十二)——3D先验的使用

文章目录 零、最近感受和前言一、使用能够快速得到重建初始化的方法1.1 Colmap(多视角)1.2 深度估计(单视角)二、已知形状模板2.1 人脸2.2 人体2.3 动物三、刚性与非刚性约束(变形约束)3.1 刚性变形3.2 非刚性变形四、统计(深度学习)先验——从大量(3D)数据中提取信息…...

DDoS技术解析

这里是Themberfue 今天我们不聊别的&#xff0c;我们聊聊著名的网络攻击手段之一的 DDoS&#xff0c;看看其背后的技术细节。 DoS 了解 DDoS 前&#xff0c;先来讲讲 DoS 是什么&#xff0c;此 DoS 而不是 DOS 操作系统啊。1996年9月6日&#xff0c;世界第三古老的网络服务提供…...

总结:如何在SpringBoot中使用https协议以及自签证书?

总结&#xff1a;如何在SpringBoot中使用https协议以及自签证书&#xff1f; 前提一&#xff1a;什么是http协议&#xff1f;前提二&#xff1a;什么是https协议&#xff1f;一生成自签证书二 将证书转换为PKCS12格式三 配置SpringBoot&#xff08;1&#xff09;修改配置文件&a…...

Django开发入门 – 4.创建Django app

Django开发入门 – 4.创建Django app Create A Django App Under An Existing Project By JacksonML 1. 什么是Django app? Django项目面向Web应用程序&#xff0c;它会由一个或多个子模块组成&#xff0c;这些子模块称为apps。 Django apps负责执行完整Web应用程序中涉及…...

安装WPS后,导致python调用Excel.Application异常,解决办法

在使用xlwings编辑excel文件时&#xff0c;默认调用的是“Excel.Application”&#xff0c;如果安装过wps&#xff0c;会导致该注册表为WPS&#xff0c;会导致xlwings执行异常 因为安装过WPS&#xff0c;导致与Excel不兼容的问题&#xff0c;想必大家都听说过。有些问题及时删…...

语言大模型基础概念 一(先了解听说过的名词都是什么)

SFT&#xff08;监督微调&#xff09;和RLHF&#xff08;基于人类反馈的强化学习&#xff09;的区别 STF&#xff08;Supervised Fine-Tuning&#xff09;和RLHF&#xff08;Reinforcement Learning from Human Feedback&#xff09;是两种不同的模型训练方法&#xff0c;分别…...

理解 WebGPU 的入口: navigator.gpu

在现代 Web 开发中&#xff0c;WebGPU 已经成为实现高性能图形渲染和计算的强大工具。作为 WebGPU API 的入口点&#xff0c; navigator.gpu 是开发者与 GPU 交互的起点。本文将详细介绍 navigator.gpu 的属性和方法&#xff0c;以及如何通过它初始化 WebGPU 环境。 什…...

Django 创建第一个项目

Django 创建第一个项目 引言 Django 是一个高级的 Python Web 框架,它鼓励快速开发和干净、实用的设计。本指南将带您从头开始创建一个简单的 Django 项目,以便您能够熟悉 Django 的基本结构和概念。 准备工作 在开始之前,请确保您已经安装了 Python 和 Django。以下是安…...

ChatGPT vs DeepSeek详细对比

&#x1f4a1; AI模型发展背景 OpenAI的GPT系列需要数据参数算力&#xff0c;这些要素共同推动了模型的成长。但是&#xff0c;到了GPT-5时代&#xff0c;人类现有的知识精华几乎被学习殆尽&#xff0c;模型的提升空间变得有限。于是OpenAI团队另辟蹊径&#xff0c;尝试模拟人…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

接口 RESTful 中的超媒体:REST 架构的灵魂驱动

在 RESTful 架构中&#xff0c;** 超媒体&#xff08;Hypermedia&#xff09;** 是一个核心概念&#xff0c;它体现了 REST 的 “表述性状态转移&#xff08;Representational State Transfer&#xff09;” 的本质&#xff0c;也是区分 “真 RESTful API” 与 “伪 RESTful AP…...