rerender-lens 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.
- package/CHANGELOG.md +95 -6
- package/README.md +156 -74
- package/dist/index.cjs +1051 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -22
- package/dist/index.d.ts +232 -22
- package/dist/index.js +1028 -10
- package/dist/index.js.map +1 -1
- package/package.json +10 -24
- package/dist/chunk-3YHI7BCU.js +0 -544
- package/dist/chunk-3YHI7BCU.js.map +0 -1
- package/dist/chunk-DOYB4MKH.cjs +0 -562
- package/dist/chunk-DOYB4MKH.cjs.map +0 -1
- package/dist/jsx-dev-runtime.cjs +0 -32
- package/dist/jsx-dev-runtime.cjs.map +0 -1
- package/dist/jsx-dev-runtime.d.cts +0 -8
- package/dist/jsx-dev-runtime.d.ts +0 -8
- package/dist/jsx-dev-runtime.js +0 -9
- package/dist/jsx-dev-runtime.js.map +0 -1
- package/dist/jsx-runtime.cjs +0 -34
- package/dist/jsx-runtime.cjs.map +0 -1
- package/dist/jsx-runtime.d.cts +0 -9
- package/dist/jsx-runtime.d.ts +0 -9
- package/dist/jsx-runtime.js +0 -10
- package/dist/jsx-runtime.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as ReactNS from 'react';
|
|
2
|
-
|
|
3
1
|
/** Why a single prop/state/hook value differs between two renders. */
|
|
4
2
|
type ChangeKind =
|
|
5
3
|
/** New reference, but deep-equal to the previous value. Avoidable. */
|
|
@@ -34,15 +32,43 @@ type RenderTrigger =
|
|
|
34
32
|
/** More than one of the above. */
|
|
35
33
|
| 'mixed';
|
|
36
34
|
interface HookChange extends Change {
|
|
37
|
-
/** `useState`, `useReducer`, `useContext`,
|
|
35
|
+
/** `useState`, `useReducer`, `useContext`, `useSyncExternalStore`, or `state` when the exact hook is unknown. */
|
|
38
36
|
hook: string;
|
|
39
37
|
/** Position of the hook in call order (0-based). */
|
|
40
38
|
index: number;
|
|
39
|
+
/** `useContext` only: the component that renders the nearest matching Provider, and its ancestry. */
|
|
40
|
+
provider?: {
|
|
41
|
+
component: string | null;
|
|
42
|
+
path: string[];
|
|
43
|
+
};
|
|
44
|
+
/** `useContext` only, object values: top-level keys whose value changed (shallow), and how many keys the value has. */
|
|
45
|
+
changedKeys?: string[];
|
|
46
|
+
totalKeys?: number;
|
|
47
|
+
}
|
|
48
|
+
/** Scheduler priority of the commit, as React reports it to the DevTools hook (transitions run at `normal`). */
|
|
49
|
+
type CommitPriority = 'immediate' | 'user-blocking' | 'normal' | 'low' | 'idle';
|
|
50
|
+
interface ParentInfo {
|
|
51
|
+
/** Display name of the nearest ancestor component that also rendered in this commit. */
|
|
52
|
+
name: string;
|
|
53
|
+
/** Why that ancestor rendered. */
|
|
54
|
+
trigger: RenderTrigger;
|
|
55
|
+
}
|
|
56
|
+
/** Where a component's element was created (React <= 18: `_debugSource`; React 19: parsed from `_debugStack`). */
|
|
57
|
+
interface SourceLocation {
|
|
58
|
+
fileName: string;
|
|
59
|
+
lineNumber?: number;
|
|
60
|
+
columnNumber?: number;
|
|
41
61
|
}
|
|
42
62
|
interface RenderReport {
|
|
43
63
|
/** Display name of the tracked component. */
|
|
44
64
|
component: string;
|
|
45
|
-
/**
|
|
65
|
+
/** Stable id of this component instance (fiber) across its lifetime. */
|
|
66
|
+
instanceId: number;
|
|
67
|
+
/** Monotonic id of the React commit that produced this report. Reports from one commit share it. 0 for `useWhyRerender`. */
|
|
68
|
+
commitId: number;
|
|
69
|
+
/** Priority React assigned to the commit: `immediate` for discrete input (clicks, keys), `user-blocking` for continuous input, `normal` for transitions and async updates. */
|
|
70
|
+
commitPriority?: CommitPriority;
|
|
71
|
+
/** Monotonic per-instance update count (1 = first update; mount is never reported). */
|
|
46
72
|
renderCount: number;
|
|
47
73
|
trigger: RenderTrigger;
|
|
48
74
|
/** True when the re-render produced no genuine change in props, state, or hooks. */
|
|
@@ -54,8 +80,22 @@ interface RenderReport {
|
|
|
54
80
|
propChanges: Change[];
|
|
55
81
|
/** Class components only. */
|
|
56
82
|
stateChanges: Change[];
|
|
57
|
-
/** Function components
|
|
83
|
+
/** Function components: state hooks and contexts that changed. */
|
|
58
84
|
hookChanges: HookChange[];
|
|
85
|
+
/** Nearest ancestor that rendered in the same commit, or null when the update started here. */
|
|
86
|
+
parent: ParentInfo | null;
|
|
87
|
+
/** Component that created this element (dev builds only). */
|
|
88
|
+
owner: string | null;
|
|
89
|
+
/** Component ancestry from the root down to this component, display names only. */
|
|
90
|
+
path: string[];
|
|
91
|
+
/** True for `React.memo` components and `PureComponent` classes: props alone decide whether they re-render. */
|
|
92
|
+
memoized: boolean;
|
|
93
|
+
/** Time spent in this component's own render (children excluded), in ms, when React exposes it (dev/profiling builds). */
|
|
94
|
+
selfDuration?: number;
|
|
95
|
+
/** Time spent rendering this component and everything below it that rendered in the same commit, in ms. */
|
|
96
|
+
treeDuration?: number;
|
|
97
|
+
/** Source location of the element that rendered this component, when React exposes it (dev builds). */
|
|
98
|
+
source?: SourceLocation;
|
|
59
99
|
/** Human-readable explanations and suggested fixes. */
|
|
60
100
|
reasons: string[];
|
|
61
101
|
/** `performance.now()` (or `Date.now()`) when the report was produced. */
|
|
@@ -72,7 +112,7 @@ interface Options {
|
|
|
72
112
|
include?: ComponentMatcher[];
|
|
73
113
|
/** Components never to track, even when marked. */
|
|
74
114
|
exclude?: ComponentMatcher[];
|
|
75
|
-
/**
|
|
115
|
+
/** Diff hook state and contexts of function components. Default true. */
|
|
76
116
|
trackHooks?: boolean;
|
|
77
117
|
/** Report re-renders caused by genuine changes too, not only avoidable ones. Default false. */
|
|
78
118
|
logAll?: boolean;
|
|
@@ -84,27 +124,26 @@ interface Options {
|
|
|
84
124
|
collapse?: boolean;
|
|
85
125
|
/** Console-like sink used for printing. Default `console`. */
|
|
86
126
|
console?: Pick<Console, 'log' | 'group' | 'groupCollapsed' | 'groupEnd' | 'warn'>;
|
|
127
|
+
/** Skip commits caused by Fast Refresh / hot module replacement. Default true. */
|
|
128
|
+
ignoreHotReload?: boolean;
|
|
129
|
+
/** Stop printing a component after this many reports (0 = unlimited). The notifier still receives them. Default 0. */
|
|
130
|
+
maxReportsPerComponent?: number;
|
|
87
131
|
}
|
|
88
|
-
/**
|
|
89
|
-
* The React object to patch. Structural so that both `import React from 'react'`
|
|
90
|
-
* and `import * as React from 'react'` type-check.
|
|
91
|
-
*/
|
|
92
|
-
type ReactLike = Pick<typeof ReactNS, 'createElement' | 'memo' | 'forwardRef' | 'useRef'> & Partial<Pick<typeof ReactNS, 'useState' | 'useReducer' | 'useContext' | 'useSyncExternalStore'>>;
|
|
93
132
|
/** Marker static: `MyComponent.rerenderLens = true` opts a component in. */
|
|
94
133
|
declare const MARKER: "rerenderLens";
|
|
95
134
|
|
|
96
|
-
type AnyType = any;
|
|
97
135
|
declare function getDisplayName(type: unknown): string;
|
|
98
|
-
/**
|
|
99
|
-
declare function
|
|
136
|
+
/** Decide whether a component type is tracked under the given options. */
|
|
137
|
+
declare function shouldTrack(type: unknown, o: Options): boolean;
|
|
100
138
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
139
|
+
* Start reporting re-renders of tracked components. Observes React commits
|
|
140
|
+
* through the DevTools global hook; nothing in React is patched or wrapped.
|
|
141
|
+
* Returns a function that stops reporting.
|
|
103
142
|
*/
|
|
104
|
-
declare function init(
|
|
105
|
-
/**
|
|
143
|
+
declare function init(options?: Options): () => void;
|
|
144
|
+
/** Merge options at runtime. Takes effect on the next commit. */
|
|
106
145
|
declare function configure(options: Options): void;
|
|
107
|
-
/**
|
|
146
|
+
/** Stop reporting and restore the DevTools hook callback. */
|
|
108
147
|
declare function disable(): void;
|
|
109
148
|
declare function isEnabled(): boolean;
|
|
110
149
|
/**
|
|
@@ -113,6 +152,86 @@ declare function isEnabled(): boolean;
|
|
|
113
152
|
*/
|
|
114
153
|
declare function track<T>(component: T, name?: string): T;
|
|
115
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Fiber-tree inspection. Runs after every React commit via the DevTools global
|
|
157
|
+
* hook, exactly like React DevTools itself. Element types are never touched, so
|
|
158
|
+
* Fast Refresh, memo comparators and component identity all stay intact.
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
interface ContextDependency {
|
|
162
|
+
context: {
|
|
163
|
+
displayName?: string;
|
|
164
|
+
_currentValue?: unknown;
|
|
165
|
+
};
|
|
166
|
+
memoizedValue: unknown;
|
|
167
|
+
next: ContextDependency | null;
|
|
168
|
+
}
|
|
169
|
+
interface Fiber {
|
|
170
|
+
tag: number;
|
|
171
|
+
key: unknown;
|
|
172
|
+
type: unknown;
|
|
173
|
+
elementType: unknown;
|
|
174
|
+
stateNode: unknown;
|
|
175
|
+
memoizedProps: Record<string, unknown> | null;
|
|
176
|
+
memoizedState: unknown;
|
|
177
|
+
alternate: Fiber | null;
|
|
178
|
+
child: Fiber | null;
|
|
179
|
+
sibling: Fiber | null;
|
|
180
|
+
return: Fiber | null;
|
|
181
|
+
flags?: number;
|
|
182
|
+
/** React 16 name for `flags`. */
|
|
183
|
+
effectTag?: number;
|
|
184
|
+
dependencies?: {
|
|
185
|
+
firstContext: ContextDependency | null;
|
|
186
|
+
} | null;
|
|
187
|
+
_debugOwner?: {
|
|
188
|
+
type?: unknown;
|
|
189
|
+
name?: string;
|
|
190
|
+
} | null;
|
|
191
|
+
_debugHookTypes?: string[] | null;
|
|
192
|
+
/** React <= 18 with the JSX dev transform. */
|
|
193
|
+
_debugSource?: {
|
|
194
|
+
fileName?: string;
|
|
195
|
+
lineNumber?: number;
|
|
196
|
+
columnNumber?: number;
|
|
197
|
+
} | null;
|
|
198
|
+
/** React 19: an Error captured where the element was created. */
|
|
199
|
+
_debugStack?: {
|
|
200
|
+
stack?: string;
|
|
201
|
+
} | string | null;
|
|
202
|
+
actualDuration?: number;
|
|
203
|
+
}
|
|
204
|
+
interface FiberRoot {
|
|
205
|
+
current: Fiber;
|
|
206
|
+
}
|
|
207
|
+
/** What `react-dom` passes to `hook.inject`. */
|
|
208
|
+
interface RendererInfo {
|
|
209
|
+
version?: string;
|
|
210
|
+
/** 1 = development build, 0 = production build. */
|
|
211
|
+
bundleType?: number;
|
|
212
|
+
rendererPackageName?: string;
|
|
213
|
+
}
|
|
214
|
+
interface DevtoolsHook {
|
|
215
|
+
renderers: Map<number, unknown>;
|
|
216
|
+
supportsFiber: boolean;
|
|
217
|
+
inject(renderer: unknown): number;
|
|
218
|
+
onCommitFiberRoot?: (id: number, root: FiberRoot, priority?: unknown, didError?: boolean) => void;
|
|
219
|
+
onCommitFiberUnmount?: (id: number, fiber: Fiber) => void;
|
|
220
|
+
onScheduleFiberRoot?: (id: number, root: FiberRoot, children: unknown) => void;
|
|
221
|
+
onPostCommitFiberRoot?: (id: number, root: FiberRoot) => void;
|
|
222
|
+
isDisabled?: boolean;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Make sure `window.__REACT_DEVTOOLS_GLOBAL_HOOK__` exists. React DOM only looks
|
|
226
|
+
* for it once, when the `react-dom` module is evaluated, so this must run before
|
|
227
|
+
* that unless the React DevTools extension or Fast Refresh already created it.
|
|
228
|
+
*/
|
|
229
|
+
declare function ensureDevtoolsHook(): DevtoolsHook;
|
|
230
|
+
/** The renderers React registered on the hook (version and dev/prod bundle type). */
|
|
231
|
+
declare function getRenderers(): RendererInfo[];
|
|
232
|
+
/** True when every registered React renderer is a production build (names minified, no hook labels). */
|
|
233
|
+
declare function isProductionReact(): boolean;
|
|
234
|
+
|
|
116
235
|
type HookOptions = Pick<Options, 'notifier' | 'silent' | 'console' | 'collapse' | 'logAll'>;
|
|
117
236
|
/**
|
|
118
237
|
* Track one component from the inside, without patching React:
|
|
@@ -147,12 +266,23 @@ declare function diffRecords(prev: Record<string, unknown> | undefined | null, n
|
|
|
147
266
|
|
|
148
267
|
interface BuildInput {
|
|
149
268
|
component: string;
|
|
269
|
+
instanceId?: number;
|
|
150
270
|
renderCount: number;
|
|
151
271
|
prevProps: Record<string, unknown>;
|
|
152
272
|
nextProps: Record<string, unknown>;
|
|
153
273
|
propChanges: Change[];
|
|
154
274
|
stateChanges?: Change[];
|
|
155
275
|
hookChanges?: HookChange[];
|
|
276
|
+
parent?: ParentInfo | null;
|
|
277
|
+
owner?: string | null;
|
|
278
|
+
path?: string[];
|
|
279
|
+
/** Default true: `useWhyRerender` and the console output assume the component decides on props alone. */
|
|
280
|
+
memoized?: boolean;
|
|
281
|
+
selfDuration?: number;
|
|
282
|
+
treeDuration?: number;
|
|
283
|
+
commitId?: number;
|
|
284
|
+
commitPriority?: CommitPriority;
|
|
285
|
+
source?: SourceLocation;
|
|
156
286
|
}
|
|
157
287
|
declare function buildReport(input: BuildInput): RenderReport;
|
|
158
288
|
declare function summarize(report: RenderReport): string;
|
|
@@ -175,13 +305,53 @@ declare function createCollector(): Collector;
|
|
|
175
305
|
declare function combineNotifiers(...notifiers: Array<Notifier | undefined | null | false>): Notifier;
|
|
176
306
|
|
|
177
307
|
declare const DEVTOOLS_MARKER: "__rerenderLens";
|
|
178
|
-
|
|
308
|
+
/** Bumped when the message shape or bridge API changes in a way the panel must know about. */
|
|
309
|
+
declare const PROTOCOL_VERSION = 2;
|
|
179
310
|
interface DevtoolsMessage {
|
|
180
311
|
[DEVTOOLS_MARKER]: true;
|
|
181
312
|
version: number;
|
|
182
313
|
type: 'report' | 'clear' | 'hello';
|
|
183
314
|
payload?: unknown;
|
|
184
315
|
}
|
|
316
|
+
/** Payload of a `hello` message. */
|
|
317
|
+
interface HelloPayload {
|
|
318
|
+
/** Buffered reports available for `replay()` / `pull()`. */
|
|
319
|
+
count: number;
|
|
320
|
+
/** Library version. */
|
|
321
|
+
library: string;
|
|
322
|
+
protocol: number;
|
|
323
|
+
react: RendererInfo[];
|
|
324
|
+
/** True when every React renderer on the page is a production build. */
|
|
325
|
+
production: boolean;
|
|
326
|
+
enabled: boolean;
|
|
327
|
+
options: SerializableOptions;
|
|
328
|
+
/** Who created this bridge: the page's own `init` call, or the extension's injected copy. */
|
|
329
|
+
source: 'page' | 'extension';
|
|
330
|
+
/** True when the extension injected a copy of the library into this page (whether or not it is the active one). */
|
|
331
|
+
injected: boolean;
|
|
332
|
+
/** Roots React scheduled (dev builds) and commits observed since `init`; the gap is work that never committed. */
|
|
333
|
+
scheduled: number;
|
|
334
|
+
commits: number;
|
|
335
|
+
}
|
|
336
|
+
declare global {
|
|
337
|
+
interface Window {
|
|
338
|
+
/** Set by the extension's inject script: version of the injected library. */
|
|
339
|
+
__RERENDER_LENS_INJECTED__?: string;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/** `Options` with matchers as strings (`"Name"` or `"/regex/flags"`) and no functions. */
|
|
343
|
+
interface SerializableOptions {
|
|
344
|
+
trackAllMemoized?: boolean;
|
|
345
|
+
trackAllComponents?: boolean;
|
|
346
|
+
include?: string[];
|
|
347
|
+
exclude?: string[];
|
|
348
|
+
trackHooks?: boolean;
|
|
349
|
+
logAll?: boolean;
|
|
350
|
+
silent?: boolean;
|
|
351
|
+
collapse?: boolean;
|
|
352
|
+
ignoreHotReload?: boolean;
|
|
353
|
+
maxReportsPerComponent?: number;
|
|
354
|
+
}
|
|
185
355
|
interface DevtoolsNotifierOptions {
|
|
186
356
|
/** How many reports to keep for `replay()`. Default 300. */
|
|
187
357
|
bufferSize?: number;
|
|
@@ -189,6 +359,25 @@ interface DevtoolsNotifierOptions {
|
|
|
189
359
|
target?: Pick<Window, 'postMessage'>;
|
|
190
360
|
/** Max serialization depth. Default 6. */
|
|
191
361
|
maxDepth?: number;
|
|
362
|
+
/** Flash the DOM of components that re-rendered avoidably. Default false; toggle later with `flashAvoidable`. */
|
|
363
|
+
flashAvoidable?: boolean;
|
|
364
|
+
/** Reported in `info()`. The extension's inject script passes `'extension'`. Default `'page'`. */
|
|
365
|
+
source?: 'page' | 'extension';
|
|
366
|
+
}
|
|
367
|
+
interface InspectResult {
|
|
368
|
+
component: string;
|
|
369
|
+
instanceId: number | null;
|
|
370
|
+
tracked: boolean;
|
|
371
|
+
path: string[];
|
|
372
|
+
/** Serialized reports for this instance, oldest first. */
|
|
373
|
+
reports: unknown[];
|
|
374
|
+
}
|
|
375
|
+
interface PullResult {
|
|
376
|
+
/** Sequence number of the newest report included; pass it back as `since`. */
|
|
377
|
+
seq: number;
|
|
378
|
+
reports: unknown[];
|
|
379
|
+
/** True when the caller missed reports that fell out of the buffer. */
|
|
380
|
+
dropped: boolean;
|
|
192
381
|
}
|
|
193
382
|
interface DevtoolsBridge {
|
|
194
383
|
/** Re-post every buffered report (a panel that opened late calls this). */
|
|
@@ -196,6 +385,21 @@ interface DevtoolsBridge {
|
|
|
196
385
|
clear(): void;
|
|
197
386
|
readonly size: number;
|
|
198
387
|
readonly version: number;
|
|
388
|
+
/** Library version. */
|
|
389
|
+
readonly library: string;
|
|
390
|
+
/** Everything the panel shows in its status line. */
|
|
391
|
+
info(): HelloPayload;
|
|
392
|
+
/** Reports newer than `since`. Lets a panel poll without any content script. */
|
|
393
|
+
pull(since?: number): PullResult;
|
|
394
|
+
/** Merge options at runtime; matchers are strings (`"/^Grid/"` becomes a RegExp). */
|
|
395
|
+
configure(options: SerializableOptions): SerializableOptions;
|
|
396
|
+
getOptions(): SerializableOptions;
|
|
397
|
+
/** Outline the DOM of an instance in the page; `null` clears. */
|
|
398
|
+
highlight(instanceId: number | null): boolean;
|
|
399
|
+
/** Turn the avoidable-render flash on or off. */
|
|
400
|
+
flashAvoidable(on: boolean): void;
|
|
401
|
+
/** Re-render details for a DOM node (DevTools' `$0`). */
|
|
402
|
+
inspect(node: unknown): InspectResult | null;
|
|
199
403
|
}
|
|
200
404
|
declare global {
|
|
201
405
|
interface Window {
|
|
@@ -204,10 +408,16 @@ declare global {
|
|
|
204
408
|
}
|
|
205
409
|
/** Convert a report into a structured-clone-safe value (functions, elements, cycles removed). */
|
|
206
410
|
declare function serialize(value: unknown, maxDepth?: number, seen?: WeakSet<object>, depth?: number): unknown;
|
|
411
|
+
/** The current options in a JSON-safe form (function matchers and custom consoles are dropped). */
|
|
412
|
+
declare function serializeOptions(o: Options): SerializableOptions;
|
|
413
|
+
declare function deserializeOptions(o: SerializableOptions): Options;
|
|
207
414
|
/**
|
|
208
415
|
* A notifier that posts every report on `window` for a DevTools extension to pick up.
|
|
209
|
-
* Also installs `window.__RERENDER_LENS_DEVTOOLS__` with `replay()` / `clear()
|
|
416
|
+
* Also installs `window.__RERENDER_LENS_DEVTOOLS__` with `replay()` / `clear()` / `pull()` and friends.
|
|
210
417
|
*/
|
|
211
418
|
declare function createDevtoolsNotifier(options?: DevtoolsNotifierOptions): Notifier;
|
|
212
419
|
|
|
213
|
-
|
|
420
|
+
/** Library version, injected by the build; "dev" when running from source. */
|
|
421
|
+
declare const VERSION: string;
|
|
422
|
+
|
|
423
|
+
export { type Change, type ChangeKind, type Collector, type ComponentMatcher, DEVTOOLS_MARKER, type DevtoolsBridge, type DevtoolsMessage, type DevtoolsNotifierOptions, type HelloPayload, type HookChange, type InspectResult, MARKER, type Notifier, type Options, PROTOCOL_VERSION, type ParentInfo, type PullResult, type RenderReport, type RenderTrigger, type RendererInfo, type SerializableOptions, type SourceLocation, VERSION, buildReport, classify, combineNotifiers, configure, createCollector, createDevtoolsNotifier, deepEqual, deserializeOptions, diffRecords, disable, ensureDevtoolsHook, getDisplayName, getRenderers, init, isEnabled, isProductionReact, printReport, serialize, serializeOptions, shouldTrack, summarize, track, useWhyRerender };
|