rerender-lens 0.1.0 → 0.3.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 +164 -6
- package/README.md +298 -75
- package/dist/budget-COBu7jBU.d.cts +64 -0
- package/dist/budget-LkNjGtRc.d.ts +64 -0
- package/dist/cli.cjs +458 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +4 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +452 -0
- package/dist/cli.js.map +1 -0
- package/dist/devtools-BHGUUo-p.d.ts +244 -0
- package/dist/devtools-DmhWiWcN.d.cts +244 -0
- package/dist/index.cjs +1686 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -153
- package/dist/index.d.ts +67 -153
- package/dist/index.js +1643 -13
- package/dist/index.js.map +1 -1
- package/dist/notifiers-BGQtWKfX.d.cts +90 -0
- package/dist/notifiers-BjjGSHpp.d.ts +90 -0
- package/dist/playwright.cjs +196 -0
- package/dist/playwright.cjs.map +1 -0
- package/dist/playwright.d.cts +35 -0
- package/dist/playwright.d.ts +35 -0
- package/dist/playwright.js +184 -0
- package/dist/playwright.js.map +1 -0
- package/dist/relay.cjs +166 -0
- package/dist/relay.cjs.map +1 -0
- package/dist/relay.d.cts +41 -0
- package/dist/relay.d.ts +41 -0
- package/dist/relay.js +161 -0
- package/dist/relay.js.map +1 -0
- package/dist/rerender-lens.iife.js +1717 -0
- package/dist/setup.cjs +1510 -0
- package/dist/setup.cjs.map +1 -0
- package/dist/setup.d.cts +2 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.js +1508 -0
- package/dist/setup.js.map +1 -0
- package/dist/types-BzUEVkxJ.d.cts +177 -0
- package/dist/types-BzUEVkxJ.d.ts +177 -0
- package/dist/vite.cjs +113 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +84 -0
- package/dist/vite.d.ts +84 -0
- package/dist/vite.js +103 -0
- package/dist/vite.js.map +1 -0
- package/dist/vitest-setup.cjs +1299 -0
- package/dist/vitest-setup.cjs.map +1 -0
- package/dist/vitest-setup.d.cts +8 -0
- package/dist/vitest-setup.d.ts +8 -0
- package/dist/vitest-setup.js +1297 -0
- package/dist/vitest-setup.js.map +1 -0
- package/dist/vitest.cjs +1360 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +52 -0
- package/dist/vitest.d.ts +52 -0
- package/dist/vitest.js +1351 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +83 -17
- package/panel/panel.css +418 -0
- package/panel/panel.html +12 -0
- package/panel/panel.js +3325 -0
- 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/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,173 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- **`npx rerender-lens panel`.** A dependency-free relay (`rerender-lens/relay`) that serves the
|
|
6
|
+
panel and forwards messages between apps and panels over server-sent events and POST, so the
|
|
7
|
+
panel works for any app on any origin without the extension or Vite: Next.js, Webpack, a remote
|
|
8
|
+
dev box, a phone. `createDevtoolsNotifier({ relay })`, `window.__RERENDER_LENS_RELAY__`, or
|
|
9
|
+
`RERENDER_LENS_RELAY` / `NEXT_PUBLIC_RERENDER_LENS_RELAY` with `rerender-lens/setup`. Commands
|
|
10
|
+
(Settings, highlight, replay, clear) go back to the app; the panel re-attaches when an app
|
|
11
|
+
reloads.
|
|
12
|
+
- **`rerender-lens/vitest`.** `setupFiles: ['rerender-lens/vitest/setup']` collects every test
|
|
13
|
+
file's reports; the reporter prints the run's ranked fixes, enforces a budget file, and can
|
|
14
|
+
write a panel-compatible export. `setupRerenderLens(options, { afterAll })` for custom options
|
|
15
|
+
and `failFast`.
|
|
16
|
+
- **`rerender-lens/playwright`.** `installRerenderLens(page, options)` injects the library at
|
|
17
|
+
document start (the bundle now ships as `dist/rerender-lens.iife.js`); `pullReports`,
|
|
18
|
+
`clearReports`, `expectWithinBudget`.
|
|
19
|
+
- A second copy of the library (another bundle on the same page) no longer wraps the hook
|
|
20
|
+
again, which doubled every report.
|
|
21
|
+
|
|
22
|
+
## 0.3.0
|
|
23
|
+
|
|
24
|
+
Highlights: the panel without the extension (Vite plugin `panel: true`), the `rerender-lens/vite`
|
|
25
|
+
plugin and `rerender-lens/setup` entry, sessions with before/after comparison, custom hook names,
|
|
26
|
+
updaters and effect-loop detection, full hook/context/state snapshots, CI budgets and a CLI, the
|
|
27
|
+
side panel and window modes, and a UI refresh. Details, newest first:
|
|
28
|
+
|
|
29
|
+
- **Panel without the extension.** `rerenderLens({ panel: true })` serves the panel from the Vite
|
|
30
|
+
dev server at `/__rerender-lens/`; the app publishes on a same-origin `BroadcastChannel`
|
|
31
|
+
(`createDevtoolsNotifier({ channel })`) and the panel sends commands back over it. The `panel/`
|
|
32
|
+
directory ships in the package. `pages` limits which HTML pages get the setup script.
|
|
33
|
+
- **Overhead readout.** `info().overhead` reports the time the library spent inspecting commits
|
|
34
|
+
(total and worst commit); the panel shows it in the status tooltip.
|
|
35
|
+
- **Panel polish.** Offenders and Fixes are windowed above 200 rows (sticky header, sortable);
|
|
36
|
+
an Offenders column chooser adds *Places* and *Last seen*; the search box takes `~text` to
|
|
37
|
+
search prop, hook, context and state values; per-component notes and a *Mute* toggle (muted
|
|
38
|
+
components leave the Fixes ranking and the summary strip, persisted per origin); roles and
|
|
39
|
+
ARIA states on the tree, lists, toast and settings dialog, Escape closes Settings.
|
|
40
|
+
- **CI tooling.** `rankFixes` / `formatFixes`, `summarizeReports` / `compareSummaries`, and
|
|
41
|
+
`checkBudget` / `toBudget` / `assertWithinBudget` in the package; the collector gains
|
|
42
|
+
`fixes()`, `summary()` and `assertWithinBudget()`, and `assertNoAvoidable()` now ends with the
|
|
43
|
+
ranked fixes. A `rerender-lens` CLI (`fixes`, `summary --out`, `compare`, `budget --init`)
|
|
44
|
+
works on panel exports and session files and exits non-zero on regressions or violations.
|
|
45
|
+
- **Source context.** The report shows the lines around where the element was created (DevTools
|
|
46
|
+
resources or a fetch of the module in side-panel mode).
|
|
47
|
+
- **Shareable links.** *Copy link* puts the report into a `panel.html?report=…` URL (deflated when
|
|
48
|
+
the browser can); anyone with the extension opens it without the page.
|
|
49
|
+
- **Custom hook names, opt-in** (`resolveHookNames`, also in Settings): hook changes and
|
|
50
|
+
snapshots read `useCounter › useCart › useState#0`. Like React DevTools, the library re-runs a
|
|
51
|
+
component type once with a stand-in dispatcher and reads the custom hooks off the call stack;
|
|
52
|
+
results are cached per type and a failing replay yields no names.
|
|
53
|
+
- **Updaters.** Every report names the components that scheduled the commit (`updaters`, from
|
|
54
|
+
React's updater tracking), so the Commits view shows "set by <X>" even when X is untracked.
|
|
55
|
+
- **Effect loops.** A commit scheduled right after the previous one by a component that rendered
|
|
56
|
+
in it is flagged `effect-after-commit` with the offending commit id; the report explains the
|
|
57
|
+
effect → setState pattern. Suspense boundaries resolving are labelled `suspense-resolved`.
|
|
58
|
+
- **Store advice.** A `useSyncExternalStore` snapshot with equal contents now gets Redux
|
|
59
|
+
(`shallowEqual` / `createSelector`) or Zustand (`useShallow`) advice when the hook chain
|
|
60
|
+
identifies the store hook.
|
|
61
|
+
- **Instances.** Reports carry the element `key`; the tree can group by instance
|
|
62
|
+
(`<Row key="a">`, `<Row #12>`) via the Instances toggle.
|
|
63
|
+
- **`rerender-lens/vite`**: a Vite plugin that starts the library before React in dev, with the
|
|
64
|
+
DevTools notifier, from one line in `vite.config.ts`. **`rerender-lens/setup`**: a side-effect
|
|
65
|
+
entry for Next.js `instrumentation-client.ts`, Webpack entry arrays and the like.
|
|
66
|
+
- CI lints the Firefox package with `web-ext lint`; `extension/store/QA.md` is the manual
|
|
67
|
+
checklist for what no test reaches. A docs site builds from the READMEs (`npm run build:docs`)
|
|
68
|
+
and deploys to GitHub Pages; `npm run docs:media` captures its screenshots and GIF.
|
|
69
|
+
- **Full state on every report.** `hookState` (every `useState` / `useReducer` /
|
|
70
|
+
`useSyncExternalStore` value), `contexts` (every context the component reads) and, for class
|
|
71
|
+
components, `state`. The panel's report shows Hooks, State and Contexts in full, with the
|
|
72
|
+
changed entries as prev → next; the console prints them too. `includeState: false` turns it off
|
|
73
|
+
(also in the panel's Settings).
|
|
74
|
+
- **Sessions.** Record, use the app, Stop; apply a fix; record again. The Sessions view compares
|
|
75
|
+
two sessions: avoidable re-renders per component with deltas, totals, wasted time, and which
|
|
76
|
+
suggested fixes went away. Summaries persist per origin; exports include them.
|
|
77
|
+
- **Provider attribution.** A `useContext` change now names the component that renders the
|
|
78
|
+
Provider and, for object values, which keys changed. When only some keys changed the reason
|
|
79
|
+
and the Fixes view say so and suggest splitting the context or selecting slices.
|
|
80
|
+
- **Children diffs.** Elements are serialized with their props, so a changed `children` prop
|
|
81
|
+
shows the differing leaf (`children[0].props.label`); re-created children get their own advice
|
|
82
|
+
and fix snippet (memoize or hoist them).
|
|
83
|
+
- **Commit priority.** Every report carries the priority React gave the commit (discrete input,
|
|
84
|
+
continuous input, transition / async, low, idle); the Commits list and report show it. The
|
|
85
|
+
bridge `info()` also counts scheduled roots vs commits.
|
|
86
|
+
- Not done: custom hook names for hook changes. React DevTools gets them by re-running the
|
|
87
|
+
component with a fake dispatcher; doing that from a commit hook is too invasive.
|
|
88
|
+
- The panel outside DevTools: **Open side panel** shows it in Chrome's side panel next to the
|
|
89
|
+
page, **Open in window** in its own window (toolbar popup, or the new buttons in the DevTools
|
|
90
|
+
panel). Both use the background relay plus `chrome.scripting` instead of DevTools APIs, follow
|
|
91
|
+
the active tab unless pinned, and stack the layout when narrower than 720px. Firefox gets the
|
|
92
|
+
same page as a sidebar.
|
|
93
|
+
- UI refresh: new palette and spacing in light and dark, icon toolbar with labels that collapse
|
|
94
|
+
in narrow layouts, segmented view switcher, a summary strip (renders, avoidable, wasted time,
|
|
95
|
+
top offender, best fix, all clickable), clearer selection and banners.
|
|
96
|
+
- `selfDuration` is now the component's own render time; the previous value (the whole subtree)
|
|
97
|
+
moved to `treeDuration`. Children that bailed out contribute nothing, as in the Profiler.
|
|
98
|
+
- `memoized` on every report (`React.memo` / `PureComponent`). Reports of unmemoized components
|
|
99
|
+
with avoidable prop changes explain that `React.memo` is needed as well; the panel's Fixes view
|
|
100
|
+
lists it first.
|
|
101
|
+
- Bridge `info()` reports `source` (`page` or `extension`) and `injected`. The panel warns when the
|
|
102
|
+
page runs its own copy next to the injected one.
|
|
103
|
+
- Extension: per-origin "Let React DevTools create the hook" toggle (popup and Settings). With it
|
|
104
|
+
on, the injector waits one task so React DevTools' own script can install the global hook first.
|
|
105
|
+
- Elements sidebar: an element without a React component above it now says so instead of
|
|
106
|
+
"not running".
|
|
107
|
+
- jsdom tests for `background.js`, `popup.js` and `sidebar.js` (shared fake `chrome`).
|
|
108
|
+
- Panel source moved to TypeScript (`extension/src/panel.ts`); `npm run build` writes the
|
|
109
|
+
committed `extension/panel.js`, and CI fails when it is out of date.
|
|
110
|
+
- Tree and live stream are virtualized (only the rows in view exist in the DOM); the stream now
|
|
111
|
+
keeps every buffered report instead of the last 300. `panel.html?demo&flood=5000` loads
|
|
112
|
+
synthetic data for scale testing.
|
|
113
|
+
- Keyboard: `/` focuses search, `f` opens the Fix tab, `Esc` clears the page highlight. The
|
|
114
|
+
details tab is remembered per origin.
|
|
115
|
+
- `different` object props show the differing leaves (`filters.page: 1 → 2`) without expanding
|
|
116
|
+
the whole value; the kind label names the first differing path.
|
|
117
|
+
- Root-cause page: click a root cause in a commit to see every commit it started, the components
|
|
118
|
+
it re-rendered avoidably, and the fixes for them.
|
|
119
|
+
|
|
120
|
+
## 0.2.0
|
|
121
|
+
|
|
122
|
+
Library
|
|
123
|
+
|
|
124
|
+
- Every report carries `commitId` (shared by the reports of one React commit) and, in dev
|
|
125
|
+
builds, `source` (`_debugSource` on React <= 18, parsed from `_debugStack` on React 19).
|
|
126
|
+
- DevTools bridge protocol 2: `hello` carries library version, protocol, React renderers and
|
|
127
|
+
options; `pull(since)` for polling panels; `info()`, `configure()`, `getOptions()`,
|
|
128
|
+
`highlight(instanceId)`, `flashAvoidable(on)` (in-page overlay), `inspect(node)`.
|
|
129
|
+
- `getRenderers()` / `isProductionReact()`: what react-dom registered on the DevTools hook.
|
|
130
|
+
`attach` wraps `hook.inject` so hooks created by react-refresh (Vite) are covered too.
|
|
131
|
+
- `serializeOptions` / `deserializeOptions`, `VERSION`.
|
|
132
|
+
- An IIFE build (`extension/vendor/rerender-lens.js`, global `RerenderLens`) for injection.
|
|
133
|
+
|
|
134
|
+
Extension
|
|
135
|
+
|
|
136
|
+
- Store-ready packaging: `npm run build:ext` writes Chrome, Edge and Firefox zips; the manifest
|
|
137
|
+
version follows `package.json`; CI uploads the zips; the release workflow publishes to the
|
|
138
|
+
Chrome Web Store when secrets are configured. Listing text and privacy policy in
|
|
139
|
+
`extension/store/`.
|
|
140
|
+
- Zero-config mode: enable an origin from the toolbar popup or the panel's Settings and tick
|
|
141
|
+
*Inject the library*; the extension loads rerender-lens into the page before React.
|
|
142
|
+
Optional host permissions for non-local hosts; local development hosts are on by default.
|
|
143
|
+
- Three-state status (no page / no library / connected with library and React versions),
|
|
144
|
+
protocol-mismatch and production-build warnings.
|
|
145
|
+
- Polling fallback through `inspectedWindow.eval` when no content script is present.
|
|
146
|
+
- New views: Offenders (sortable table), Commits (root causes, render cascade, contexts),
|
|
147
|
+
Fixes (ranked by avoidable re-renders removed, with snippets). Per-report Fix tab.
|
|
148
|
+
- Hover-to-highlight and flash of avoidable renders in the page; "open source" links into the
|
|
149
|
+
Sources panel; Copy as Markdown; JSON export/import.
|
|
150
|
+
- Settings drawer driving `configure()` live, persisted per origin; panel state (filters,
|
|
151
|
+
collapsed nodes, split width) persisted per origin.
|
|
152
|
+
- Elements-panel sidebar for `$0`; toolbar badge with the avoidable count per tab.
|
|
153
|
+
- Reports are batched per animation frame; malformed payloads are ignored.
|
|
154
|
+
- Playwright end-to-end suite (`npm run e2e`) running Chromium with the extension against the
|
|
155
|
+
example app (relay, badge, injection, panel).
|
|
156
|
+
|
|
3
157
|
## 0.1.0
|
|
4
158
|
|
|
5
159
|
Initial release.
|
|
6
160
|
|
|
7
|
-
- `init(
|
|
161
|
+
- `init(options)` observes React commits through the DevTools global hook and reports every
|
|
162
|
+
update of a tracked component. No patching, no wrappers: Fast Refresh, memo comparators,
|
|
163
|
+
forwardRef, classes and the automatic JSX runtime all work unchanged.
|
|
8
164
|
- Change classification: `deep-equal`, `function`, `element`, `different`, `added`, `removed`.
|
|
9
165
|
- Trigger classification: `props`, `parent`, `state`, `hooks`, `mixed`; `avoidable` flag.
|
|
10
|
-
-
|
|
11
|
-
|
|
166
|
+
- `parent` (nearest ancestor that rendered, and why), `owner`, `path`, `instanceId`,
|
|
167
|
+
`renderCount`, `selfDuration` on every report.
|
|
168
|
+
- Hook state (`useState`, `useReducer`, `useSyncExternalStore`) and `useContext` diffs.
|
|
169
|
+
- `useWhyRerender(name, values)` hook for tracking one component without `init`.
|
|
12
170
|
- `createCollector()` with `assertNoAvoidable()` for tests; `combineNotifiers()`.
|
|
13
|
-
- `createDevtoolsNotifier()` posting structured-clone-safe reports on `window
|
|
14
|
-
- `
|
|
15
|
-
-
|
|
171
|
+
- `createDevtoolsNotifier()` posting structured-clone-safe reports on `window`.
|
|
172
|
+
- `ignoreHotReload` and `maxReportsPerComponent` options.
|
|
173
|
+
- Example Vite app with three deliberate re-render bugs.
|