@react-perfscope/react 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +30 -40
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # @react-perfscope/react
2
2
 
3
- React 18+ adapter for `react-perfscope`. Installs a DevTools global hook to observe commits, walks fiber trees, and exposes a render collector that plugs into `@react-perfscope/core`.
3
+ React 18+ render collector for `react-perfscope`. Observes React commits and emits one `RenderSignal` per changed component, plugging into `@react-perfscope/core`.
4
4
 
5
- ## Status
5
+ ## Install
6
6
 
7
- Phase 3-4 stable. Render collector emits one `RenderSignal` per changed component per commit; `RenderSignal.duration` populated from `fiber.actualDuration` when React is built with Profiling.
7
+ ```sh
8
+ npm install @react-perfscope/react @react-perfscope/core
9
+ ```
8
10
 
9
- ## Example
11
+ ## Usage
10
12
 
11
13
  ```ts
12
14
  import { createRecorder } from '@react-perfscope/core'
@@ -22,19 +24,9 @@ const result = recorder.stop()
22
24
  console.log(result.signals.filter((s) => s.kind === 'render'))
23
25
  ```
24
26
 
25
- ## API
26
-
27
- - `createRenderCollector()` — Collector factory. Emits `RenderSignal` per non-host fiber on each React commit.
28
- - `resolveComponentFromElement(el)` — Given a DOM element, return the nearest React component name (or null if no fiber attached).
29
- - `installDevToolsHook(listener)` — Low-level DevTools hook installer. Returns an unsubscribe function. Chains with any pre-existing hook (e.g. real React DevTools).
30
- - `fiberComponentName(fiber)` — Resolve a fiber to its component name. Handles host tags, function/class components, `memo`, `forwardRef`.
31
- - `walkChangedFibers(root, visit, { stopAt })` — Depth-first traversal of a fiber subtree with an upper bound.
32
-
33
- ## Hook load-order (IMPORTANT)
34
-
35
- `react-dom` reads `globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__` ONCE at module evaluation time. If the hook isn't there at that moment, `react-dom`'s internal `injectedHook` is set to `null` and never updated — our collector will then never receive commits.
27
+ ## Load order (important)
36
28
 
37
- **Practical implication:** import `@react-perfscope/react` (or call `createRenderCollector()` / `installDevToolsHook()`) BEFORE you `import 'react-dom/client'` or before any module that does. The simplest pattern:
29
+ `react-dom` reads the DevTools global hook **once** at module-evaluation time. Import `@react-perfscope/react` (or call `createRenderCollector()`) **before** any code that imports `react-dom/client`, otherwise the collector never receives commits:
38
30
 
39
31
  ```ts
40
32
  // At the very top of your entry file
@@ -48,12 +40,15 @@ recorder.use(createRenderCollector())
48
40
  import './app'
49
41
  ```
50
42
 
51
- If you're using the `react-perfscope` meta package (or one of the build plugins), this ordering is handled automatically.
43
+ The `react-perfscope` meta package and the build plugins handle this ordering automatically.
52
44
 
53
- ## Caveats
45
+ ## API
54
46
 
55
- - The render collector keeps its DevTools hook listener attached across deactivate cycles (emission is gated by an `active` flag). This mirrors the `web-vitals` collector's lifecycle.
56
- - `RenderSignal.duration` is `0` for fibers outside a Profiler-enabled root (React's default `createRoot` is Profiler-enabled in development).
47
+ - `createRenderCollector()` Collector factory. Emits `RenderSignal` per non-host fiber on each React commit.
48
+ - `resolveComponentFromElement(el)` Given a DOM element, return the nearest React component name (or null).
49
+ - `installDevToolsHook(listener)` — Low-level DevTools hook installer. Returns an unsubscribe function.
50
+ - `fiberComponentName(fiber)` — Resolve a fiber to its component name.
51
+ - `walkChangedFibers(root, visit, { stopAt })` — Depth-first traversal of a fiber subtree with an upper bound.
57
52
 
58
53
  ---
59
54
 
@@ -61,13 +56,15 @@ If you're using the `react-perfscope` meta package (or one of the build plugins)
61
56
 
62
57
  # 한국어
63
58
 
64
- `react-perfscope`용 React 18+ 어댑터. DevTools 글로벌 훅을 설치해 커밋을 감지하고, fiber 트리를 순회해서 `@react-perfscope/core`에 연결되는 render collector를 제공한다.
59
+ `react-perfscope`용 React 18+ render collector. React 커밋을 감지해서 변경된 컴포넌트마다 `RenderSignal` 하나를 내보내고, `@react-perfscope/core`에 연결된다.
65
60
 
66
- ## 상태
61
+ ## 설치
67
62
 
68
- Phase 3-4 안정화. render collector는 커밋마다 변경된 컴포넌트 하나당 `RenderSignal` 하나를 내보낸다. React가 Profiling 빌드일 경우 `RenderSignal.duration`은 `fiber.actualDuration`으로 채워진다.
63
+ ```sh
64
+ npm install @react-perfscope/react @react-perfscope/core
65
+ ```
69
66
 
70
- ## 예제
67
+ ## 사용법
71
68
 
72
69
  ```ts
73
70
  import { createRecorder } from '@react-perfscope/core'
@@ -83,19 +80,9 @@ const result = recorder.stop()
83
80
  console.log(result.signals.filter((s) => s.kind === 'render'))
84
81
  ```
85
82
 
86
- ## API
87
-
88
- - `createRenderCollector()` — Collector 팩토리. React 커밋마다 non-host fiber에 대해 `RenderSignal`을 내보낸다.
89
- - `resolveComponentFromElement(el)` — DOM 엘리먼트를 받아 가장 가까운 React 컴포넌트 이름을 반환한다 (fiber가 없으면 null).
90
- - `installDevToolsHook(listener)` — 저수준 DevTools 훅 설치 함수. unsubscribe 함수를 반환한다. 기존에 있던 훅(예: 실제 React DevTools)이 있으면 체이닝한다.
91
- - `fiberComponentName(fiber)` — fiber를 컴포넌트 이름으로 해석한다. host 태그, 함수/클래스 컴포넌트, `memo`, `forwardRef`를 모두 처리한다.
92
- - `walkChangedFibers(root, visit, { stopAt })` — 상한선을 두고 fiber 서브트리를 깊이 우선으로 순회한다.
93
-
94
- ## 훅 로드 순서 (중요)
95
-
96
- `react-dom`은 모듈 평가 시점에 `globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__`을 딱 한 번 읽는다. 그 시점에 훅이 없으면 `react-dom` 내부의 `injectedHook`이 `null`로 고정되어 이후에 업데이트되지 않는다 — 그러면 collector가 커밋을 영원히 못 받는다.
83
+ ## 로드 순서 (중요)
97
84
 
98
- **실용적인 의미:** `@react-perfscope/react`를 import하거나 `createRenderCollector()` / `installDevToolsHook()`를 호출하는 건 반드시 `import 'react-dom/client'`보다 먼저, 그리고 그걸 import하는 어떤 모듈보다도 먼저 와야 한다. 가장 간단한 패턴:
85
+ `react-dom`은 모듈 평가 시점에 DevTools 글로벌 훅을 **딱 한 번** 읽는다. 그래서 `@react-perfscope/react`를 import하거나 `createRenderCollector()`를 호출하는 건 `react-dom/client`를 import하는 어떤 코드보다도 **먼저** 와야 한다. 그러면 collector가 커밋을 영원히 못 받는다:
99
86
 
100
87
  ```ts
101
88
  // entry 파일 맨 위에
@@ -109,9 +96,12 @@ recorder.use(createRenderCollector())
109
96
  import './app'
110
97
  ```
111
98
 
112
- `react-perfscope` 메타 패키지(또는 빌드 플러그인 중 하나)를 쓰면 이 순서가 자동으로 처리된다.
99
+ `react-perfscope` 메타 패키지나 빌드 플러그인을 쓰면 이 순서가 자동으로 처리된다.
113
100
 
114
- ## 주의사항
101
+ ## API
115
102
 
116
- - render collector는 deactivate 사이클에도 DevTools 리스너를 붙여둔다 (내보내기는 `active` 플래그로 제어된다). 이건 `web-vitals` collector의 생명주기와 같은 방식이다.
117
- - Profiler가 활성화된 root 바깥에 있는 fiber는 `RenderSignal.duration`이 `0`이다 (개발 모드의 `createRoot`는 기본적으로 Profiler가 켜져 있다).
103
+ - `createRenderCollector()` Collector 팩토리. React 커밋마다 non-host fiber에 대해 `RenderSignal`을 내보낸다.
104
+ - `resolveComponentFromElement(el)` DOM 엘리먼트를 받아 가장 가까운 React 컴포넌트 이름을 반환한다 (없으면 null).
105
+ - `installDevToolsHook(listener)` — 저수준 DevTools 훅 설치 함수. unsubscribe 함수를 반환한다.
106
+ - `fiberComponentName(fiber)` — fiber를 컴포넌트 이름으로 해석한다.
107
+ - `walkChangedFibers(root, visit, { stopAt })` — 상한선을 두고 fiber 서브트리를 깊이 우선으로 순회한다.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-perfscope/react",
3
- "version": "0.1.0",
4
- "description": "React render-cascade collector for react-perfscope: per-commit render reasons with source attribution.",
3
+ "version": "0.2.0",
4
+ "description": "React render collector for react-perfscope.",
5
5
  "keywords": [
6
6
  "react",
7
7
  "performance",
@@ -25,11 +25,11 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@react-perfscope/core": "0.1.0"
28
+ "@react-perfscope/core": "0.2.0"
29
29
  },
30
30
  "peerDependencies": {
31
- "react": "^18.3.0",
32
- "react-dom": "^18.3.0"
31
+ "react": "^18.3.0 || ^19.0.0",
32
+ "react-dom": "^18.3.0 || ^19.0.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "react": "^18.3.0",