Skip to content

Commit fb05d28

Browse files
committed
feat: react-scan文章
1 parent cf695d8 commit fb05d28

File tree

3 files changed

+76
-7
lines changed

3 files changed

+76
-7
lines changed

markdown/index.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,12 @@
55
"title": "建站",
66
"tag": "生活",
77
"coverImage": "https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg"
8+
},
9+
{
10+
"authors": ["zhw"],
11+
"path": "react-scan.md",
12+
"title": "聊聊react-scan",
13+
"tag": "react",
14+
"coverImage": "https://raw.githubusercontent.com/aidenybai/react-scan/ca7746e2808408c04bcfbfc15486368e67d72bba/.github/assets/logo.svg"
815
}
916
]

markdown/output.json

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,80 @@
11
{
22
"postDataMap": {
33
"first": {
4-
"authors": ["zhw"],
4+
"authors": [
5+
"zhw"
6+
],
57
"title": "建站",
68
"tag": "生活",
79
"path": "first",
810
"rawFilePath": "./first.md",
911
"coverImage": "https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg",
10-
"text": "记录一下建站的第一天,也许开心到爆炸.\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg)\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif)",
12+
"text": "记录一下建站的第一天,也许开心到爆炸.\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg)\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif)\r\n",
1113
"count": "268",
1214
"readingTime": "1 ",
1315
"imageUrls": [
1416
"https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg",
1517
"https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif"
1618
],
1719
"createdAt": "2024-11-13T12:48:31.000Z",
18-
"updatedAt": "2024-11-13T13:01:51.000Z",
20+
"updatedAt": "2024-11-14T08:12:55.000Z",
1921
"modified": true
22+
},
23+
"react-scan": {
24+
"authors": [
25+
"zhw"
26+
],
27+
"title": "聊聊react-scan",
28+
"tag": "react",
29+
"path": "react-scan",
30+
"rawFilePath": "./react-scan.md",
31+
"coverImage": "https://raw.githubusercontent.com/aidenybai/react-scan/ca7746e2808408c04bcfbfc15486368e67d72bba/.github/assets/logo.svg",
32+
"text": "# react - scan 核心原理剖析\r\n\r\nreact - scan 是一个用于监听react重渲染的工具,其核心原理是巧妙伪装成 React DevTools,借此成功接入 React 的内部运行机制,从而精准获取 Fiber 节点关键信息,实现对组件更新状况的实时监控。\r\n\r\nReact DevTools 在网页的 window 对象上会挂载一个特殊的全局对象:`__REACT_DEVTOOLS_GLOBAL_HOOK__`。React 在自身运行期间,于某些关键生命周期节点,会调用这个对象上的指定方法,像在 commit 阶段就会调用 `onCommitFiberRoot` 方法,并向其传入当前更新的 FiberRoot 节点作为参数。\r\n\r\nreact - scan 则利用这一点,通过劫持该 hook 上的函数,例如对 `onCommitFiberRoot` 进行重写操作,从而顺利获取整个 React 应用的 Fiber 树根节点。获取根节点后,借助 Fiber 节点的 child 属性指向第一个子节点、sibling 属性指向下一个兄弟节点,就能递归遍历整棵 Fiber 树,进而拿到每一个组件对应的 Fiber 节点详细信息。\r\n\r\n**如何判断组件是否发生更新?**\r\n\r\n * 对于非 Host 组件(即非原生 DOM 节点):通过位运算判断其 flags 与 PerformedWork 相与的结果是否为 PerformedWork,以此确定该 Fiber 节点是否发生更新。\r\n * 对于 Host 组件(对应实际 DOM 节点):\r\n * 若不存在 alternate 节点,表明是组件的首次渲染(因为 Fiber 采用双缓冲机制,存在当前树与上一次树之分)。\r\n * 若存在 alternate 节点,则对比当前与上一次的 memoizedProps(组件属性)、memoizedState(组件状态)、ref,判断组件是否更新。\r\n\r\n**如何定位更新组件的 DOM 元素?**\r\n\r\n一旦确定组件发生更新,可以从对应的 Fiber 节点向上查找最近的 Host 节点(即 Host Fiber),获取其关联的 DOM 元素,进而对 DOM 元素进行高亮或标记操作,方便进行调试或可视化展示。\r\n\r\n**一些其他功能:**\r\n\r\n * 对比两棵 Fiber 树的 memoizedProps,能够精确知晓具体哪个 prop 发生了变化。\r\n * 判断是否因 Context 变化引发的组件更新:可通过 fiber.firstContext 获取组件订阅的第一个 Context,然后凭借其 next 属性依次遍历所有订阅的 Context 节点,查找更新源头。\r\n * 判断是否因为 Hook 更新导致组件更新:鉴于 Fiber 上的 memoizedState 存储着 hooks 链表,可据此分析是哪个 state 发生了变化。",
33+
"count": "1.1k",
34+
"readingTime": "5 ",
35+
"imageUrls": [],
36+
"createdAt": null,
37+
"updatedAt": null,
38+
"modified": false
2039
}
2140
},
2241
"postDataList": [
2342
{
24-
"authors": ["zhw"],
43+
"authors": [
44+
"zhw"
45+
],
2546
"title": "建站",
2647
"tag": "生活",
2748
"path": "first",
2849
"rawFilePath": "./first.md",
2950
"coverImage": "https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg",
30-
"text": "记录一下建站的第一天,也许开心到爆炸.\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg)\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif)",
51+
"text": "记录一下建站的第一天,也许开心到爆炸.\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg)\r\n![建站图片](https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif)\r\n",
3152
"count": "268",
3253
"readingTime": "1 ",
3354
"imageUrls": [
3455
"https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg",
3556
"https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif"
3657
],
3758
"createdAt": "2024-11-13T12:48:31.000Z",
38-
"updatedAt": "2024-11-13T13:01:51.000Z",
59+
"updatedAt": "2024-11-14T08:12:55.000Z",
3960
"modified": true
61+
},
62+
{
63+
"authors": [
64+
"zhw"
65+
],
66+
"title": "聊聊react-scan",
67+
"tag": "react",
68+
"path": "react-scan",
69+
"rawFilePath": "./react-scan.md",
70+
"coverImage": "https://raw.githubusercontent.com/aidenybai/react-scan/ca7746e2808408c04bcfbfc15486368e67d72bba/.github/assets/logo.svg",
71+
"text": "# react - scan 核心原理剖析\r\n\r\nreact - scan 是一个用于监听react重渲染的工具,其核心原理是巧妙伪装成 React DevTools,借此成功接入 React 的内部运行机制,从而精准获取 Fiber 节点关键信息,实现对组件更新状况的实时监控。\r\n\r\nReact DevTools 在网页的 window 对象上会挂载一个特殊的全局对象:`__REACT_DEVTOOLS_GLOBAL_HOOK__`。React 在自身运行期间,于某些关键生命周期节点,会调用这个对象上的指定方法,像在 commit 阶段就会调用 `onCommitFiberRoot` 方法,并向其传入当前更新的 FiberRoot 节点作为参数。\r\n\r\nreact - scan 则利用这一点,通过劫持该 hook 上的函数,例如对 `onCommitFiberRoot` 进行重写操作,从而顺利获取整个 React 应用的 Fiber 树根节点。获取根节点后,借助 Fiber 节点的 child 属性指向第一个子节点、sibling 属性指向下一个兄弟节点,就能递归遍历整棵 Fiber 树,进而拿到每一个组件对应的 Fiber 节点详细信息。\r\n\r\n**如何判断组件是否发生更新?**\r\n\r\n * 对于非 Host 组件(即非原生 DOM 节点):通过位运算判断其 flags 与 PerformedWork 相与的结果是否为 PerformedWork,以此确定该 Fiber 节点是否发生更新。\r\n * 对于 Host 组件(对应实际 DOM 节点):\r\n * 若不存在 alternate 节点,表明是组件的首次渲染(因为 Fiber 采用双缓冲机制,存在当前树与上一次树之分)。\r\n * 若存在 alternate 节点,则对比当前与上一次的 memoizedProps(组件属性)、memoizedState(组件状态)、ref,判断组件是否更新。\r\n\r\n**如何定位更新组件的 DOM 元素?**\r\n\r\n一旦确定组件发生更新,可以从对应的 Fiber 节点向上查找最近的 Host 节点(即 Host Fiber),获取其关联的 DOM 元素,进而对 DOM 元素进行高亮或标记操作,方便进行调试或可视化展示。\r\n\r\n**一些其他功能:**\r\n\r\n * 对比两棵 Fiber 树的 memoizedProps,能够精确知晓具体哪个 prop 发生了变化。\r\n * 判断是否因 Context 变化引发的组件更新:可通过 fiber.firstContext 获取组件订阅的第一个 Context,然后凭借其 next 属性依次遍历所有订阅的 Context 节点,查找更新源头。\r\n * 判断是否因为 Hook 更新导致组件更新:鉴于 Fiber 上的 memoizedState 存储着 hooks 链表,可据此分析是哪个 state 发生了变化。",
72+
"count": "1.1k",
73+
"readingTime": "5 ",
74+
"imageUrls": [],
75+
"createdAt": null,
76+
"updatedAt": null,
77+
"modified": false
4078
}
4179
]
42-
}
80+
}

markdown/react-scan.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# react - scan 核心原理剖析
2+
3+
react - scan 是一个用于监听react重渲染的工具,其核心原理是巧妙伪装成 React DevTools,借此成功接入 React 的内部运行机制,从而精准获取 Fiber 节点关键信息,实现对组件更新状况的实时监控。
4+
5+
React DevTools 在网页的 window 对象上会挂载一个特殊的全局对象:`__REACT_DEVTOOLS_GLOBAL_HOOK__`。React 在自身运行期间,于某些关键生命周期节点,会调用这个对象上的指定方法,像在 commit 阶段就会调用 `onCommitFiberRoot` 方法,并向其传入当前更新的 FiberRoot 节点作为参数。
6+
7+
react - scan 则利用这一点,通过劫持该 hook 上的函数,例如对 `onCommitFiberRoot` 进行重写操作,从而顺利获取整个 React 应用的 Fiber 树根节点。获取根节点后,借助 Fiber 节点的 child 属性指向第一个子节点、sibling 属性指向下一个兄弟节点,就能递归遍历整棵 Fiber 树,进而拿到每一个组件对应的 Fiber 节点详细信息。
8+
9+
**如何判断组件是否发生更新?**
10+
11+
* 对于非 Host 组件(即非原生 DOM 节点):通过位运算判断其 flags 与 PerformedWork 相与的结果是否为 PerformedWork,以此确定该 Fiber 节点是否发生更新。
12+
* 对于 Host 组件(对应实际 DOM 节点):
13+
* 若不存在 alternate 节点,表明是组件的首次渲染(因为 Fiber 采用双缓冲机制,存在当前树与上一次树之分)。
14+
* 若存在 alternate 节点,则对比当前与上一次的 memoizedProps(组件属性)、memoizedState(组件状态)、ref,判断组件是否更新。
15+
16+
**如何定位更新组件的 DOM 元素?**
17+
18+
一旦确定组件发生更新,可以从对应的 Fiber 节点向上查找最近的 Host 节点(即 Host Fiber),获取其关联的 DOM 元素,进而对 DOM 元素进行高亮或标记操作,方便进行调试或可视化展示。
19+
20+
**一些其他功能:**
21+
22+
* 对比两棵 Fiber 树的 memoizedProps,能够精确知晓具体哪个 prop 发生了变化。
23+
* 判断是否因 Context 变化引发的组件更新:可通过 fiber.firstContext 获取组件订阅的第一个 Context,然后凭借其 next 属性依次遍历所有订阅的 Context 节点,查找更新源头。
24+
* 判断是否因为 Hook 更新导致组件更新:鉴于 Fiber 上的 memoizedState 存储着 hooks 链表,可据此分析是哪个 state 发生了变化。

0 commit comments

Comments
 (0)