rerender-lens 0.3.0 → 0.5.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 (66) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +192 -353
  3. package/dist/{budget-COBu7jBU.d.cts → budget-BnJlYwrV.d.ts} +20 -10
  4. package/dist/{budget-LkNjGtRc.d.ts → budget-CRswn-nC.d.cts} +20 -10
  5. package/dist/cli.cjs +248 -31
  6. package/dist/cli.cjs.map +1 -1
  7. package/dist/cli.js +248 -31
  8. package/dist/cli.js.map +1 -1
  9. package/dist/{devtools-BHGUUo-p.d.ts → devtools-BYWat7nQ.d.ts} +17 -3
  10. package/dist/{devtools-DmhWiWcN.d.cts → devtools-DJi_6AfJ.d.cts} +17 -3
  11. package/dist/index.cjs +635 -109
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +131 -8
  14. package/dist/index.d.ts +131 -8
  15. package/dist/index.js +620 -110
  16. package/dist/index.js.map +1 -1
  17. package/dist/jest-setup.cjs +1673 -0
  18. package/dist/jest-setup.cjs.map +1 -0
  19. package/dist/jest-setup.d.cts +8 -0
  20. package/dist/jest-setup.d.ts +8 -0
  21. package/dist/jest-setup.js +1671 -0
  22. package/dist/jest-setup.js.map +1 -0
  23. package/dist/jest.cjs +1760 -0
  24. package/dist/jest.cjs.map +1 -0
  25. package/dist/jest.d.cts +23 -0
  26. package/dist/jest.d.ts +23 -0
  27. package/dist/jest.js +1751 -0
  28. package/dist/jest.js.map +1 -0
  29. package/dist/{notifiers-BjjGSHpp.d.ts → notifiers-DwKlvv4H.d.cts} +8 -4
  30. package/dist/{notifiers-BGQtWKfX.d.cts → notifiers-FNzKHs0a.d.ts} +8 -4
  31. package/dist/playwright.cjs +235 -30
  32. package/dist/playwright.cjs.map +1 -1
  33. package/dist/playwright.d.cts +8 -6
  34. package/dist/playwright.d.ts +8 -6
  35. package/dist/playwright.js +235 -31
  36. package/dist/playwright.js.map +1 -1
  37. package/dist/relay.cjs +10 -2
  38. package/dist/relay.cjs.map +1 -1
  39. package/dist/relay.js +10 -2
  40. package/dist/relay.js.map +1 -1
  41. package/dist/rerender-lens.iife.js +1100 -337
  42. package/dist/runner-report-B8Sc3FZO.d.cts +46 -0
  43. package/dist/runner-report-CW8X5RwK.d.ts +46 -0
  44. package/dist/setup.cjs +308 -95
  45. package/dist/setup.cjs.map +1 -1
  46. package/dist/setup.js +308 -95
  47. package/dist/setup.js.map +1 -1
  48. package/dist/{types-BzUEVkxJ.d.cts → types-DW5-N2XH.d.cts} +55 -2
  49. package/dist/{types-BzUEVkxJ.d.ts → types-DW5-N2XH.d.ts} +55 -2
  50. package/dist/vite.d.cts +1 -1
  51. package/dist/vite.d.ts +1 -1
  52. package/dist/vitest-setup.cjs +452 -87
  53. package/dist/vitest-setup.cjs.map +1 -1
  54. package/dist/vitest-setup.d.cts +4 -4
  55. package/dist/vitest-setup.d.ts +4 -4
  56. package/dist/vitest-setup.js +452 -87
  57. package/dist/vitest-setup.js.map +1 -1
  58. package/dist/vitest.cjs +515 -123
  59. package/dist/vitest.cjs.map +1 -1
  60. package/dist/vitest.d.cts +21 -39
  61. package/dist/vitest.d.ts +21 -39
  62. package/dist/vitest.js +516 -124
  63. package/dist/vitest.js.map +1 -1
  64. package/package.json +41 -5
  65. package/panel/panel.css +1 -34
  66. package/panel/panel.js +865 -713
package/CHANGELOG.md CHANGED
@@ -2,6 +2,92 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - **Jest.** `rerender-lens/jest` and `rerender-lens/jest/setup`: the same deal as the Vitest
6
+ integration — one `setupFilesAfterEnv` line collects every avoidable re-render, and the reporter
7
+ (`reporters: [['rerender-lens/jest', { budget }]]`) prints the run's ranked fixes and root causes,
8
+ writes a panel-compatible export and fails the run on a budget violation. The runner-agnostic half
9
+ (the JSONL hand-off between workers and the reporter, the per-file setup, the finish logic) moved
10
+ to `src/runner-report.ts`, so Vitest and Jest share one implementation. A real Jest run in
11
+ `test/jest/` (jsdom, babel-jest, the package resolved by name) is its own CI job: it asserts the
12
+ reporter exits non-zero with a budget of zero and exits 0 with a budget that fits.
13
+
14
+ - **React 17 in CI, and the peer range is now honest.** `npm run test:react17` runs the unit suite
15
+ against React 17 alongside `test:react18`, so `react >= 16.8` is a tested claim rather than an
16
+ assumption. The harness became version-agnostic (`act` from `react` or `react-dom/test-utils`, a
17
+ shim for the root API React 17 does not have). What React 17 cannot give you is now documented in
18
+ the README's compatibility table and said once at runtime: React only records the value a
19
+ component read from a context from 18 on, so on 17 a context change is reported as a plain parent
20
+ re-render; updaters and effect-loop detection need React 18's updater tracking.
21
+ - **Report a problem** in the panel's Settings drawer: opens a GitHub issue prefilled with the
22
+ extension and library versions, React version, options, overhead, the truncation count and the
23
+ buffer totals, and nothing from the page. `extension/store/QA.md` gains the scale, relay and
24
+ help checks.
25
+ - **Verdicts on modern React.** A fixture matrix (`test/modern.test.ts`, and `/modern.html` in the
26
+ example) pins the verdict for React Compiler output, `use(promise)`, `startTransition`, Suspense
27
+ fallback → content, `useSyncExternalStore` selectors, render props, `forwardRef` + `memo` refs,
28
+ classes with `shouldComponentUpdate`, `useDeferredValue` and `useId`; the README gains the table
29
+ "What counts as avoidable". Fixes that came out of it: components compiled by React Compiler carry
30
+ `compiled: true` (detected from the `useMemoCache` slots on the fiber) and a parent-triggered render
31
+ with identical props is no longer avoidable (the output is memoized; nothing to fix); content
32
+ re-rendered because a Suspense boundary above it resolved is explained instead of flagged; a new
33
+ `ref` object per render is reported as `deep-equal` on `ref` with `useRef` advice instead of a
34
+ spurious `ref.current` change; the deferred second render of `useDeferredValue` is a `hooks` render
35
+ (dev builds) rather than an avoidable parent render, and never counts as an effect → setState loop;
36
+ class components get PureComponent / `shouldComponentUpdate` advice instead of `React.memo`. The
37
+ panel shows the compiled flag.
38
+
39
+ ## 0.5.0
40
+
41
+ Highlights: root causes in the CLI and test reporters, React 18 in CI, Next.js verified end to
42
+ end, one analysis implementation shared by the panel and the library, and Web Store assets
43
+ generated by script. Details, newest first:
44
+
45
+ - **README and docs site.** The README is half its length: a "pick a way in" table, one section
46
+ per entry point, and the reference tables trimmed to what you read. The docs site gains a hero
47
+ with the recording, a sticky table of contents and a cleaner layout; `docs/PLAN.md` holds the
48
+ plan for what comes next.
49
+ - **Store assets.** `npm run store:media` renders the five 1280x800 screenshots and the two promo
50
+ tiles the Chrome Web Store asks for into `extension/store/media/`; the e2e suite also checks the
51
+ panel stays responsive with 20,000 buffered reports (`panel.html?demo&flood=20000`).
52
+ - Root causes outside the panel. The commit analysis the DevTools panel had (`analyzeCommit`,
53
+ `rootCauseOf`, `contextAttribution`, `cascadeTree`, `rootCauseSummary`) moved into the library
54
+ (`src/causes.ts`, exported from `rerender-lens`) with `groupByCommit`, `rankRootCauses` and
55
+ `formatRootCauses` on top; the panel imports it. `formatFixes` (the CLI `fixes` command, the
56
+ Vitest reporter, `collector.assertNoAvoidable`, budget failures) now ends with a "Root causes"
57
+ section when the reports carry `commitId` (`<Page> (state) started 3 commits, 12 avoidable
58
+ re-renders`), and `rerender-lens causes export.json` prints that table alone.
59
+ - The DevTools panel and the library now share one implementation of fixes (`fixesFor`,
60
+ `rankFixes`), session summaries (`summarizeReports`/`summarizeSession`,
61
+ `compareSummaries`/`compareSessions`) and diff paths (`firstDifferentPath`, `diffLeaves`), typed
62
+ over a structural `ReportLike`. Library fixes gain the `snippet` and the context/provider
63
+ attribution the panel had; ranked fixes also carry the first 50 `reports` they apply to.
64
+ - **Next.js, verified.** `examples/next` starts the library from `instrumentation-client.ts` with
65
+ `rerender-lens/setup` and reaches the relay panel; `npm run e2e:next` drives it in Chromium
66
+ (CI too). Two bugs it found: `rerender-lens/setup` read `process.env[key]` dynamically, which no
67
+ bundler inlines, so `NEXT_PUBLIC_RERENDER_LENS_RELAY` was never seen and the entry also ran in
68
+ production builds; and a panel that opened after the app had connected to the relay never
69
+ attached (the relay now greets each panel with the current app count, and the panel sends its
70
+ first command only after that greeting, so no reply is lost to the connection race).
71
+ - **React 18 in CI.** `npm run test:react18` runs the whole unit suite against React 18 (CI job
72
+ `react18`). It found one bug: with React 18 the custom hook name replay listed React's own
73
+ `useState` wrapper as if it were a custom hook (`useState › useCounter › useCart`); frames named
74
+ like a React primitive are now skipped.
75
+ - The panel re-reads `info()` every 3 s while connected, so the overhead readout, the enabled
76
+ flag and the "reports skipped" banner stay current instead of reflecting the moment it attached.
77
+ - `npm run test:built` (in `check` and CI) loads the three built vendor scripts in order and drives
78
+ a React re-render through them; before, that test always skipped in CI because tests ran
79
+ before the build.
80
+
81
+ ## 0.4.0
82
+
83
+ Highlights: the panel for any app with `npx rerender-lens panel`, Vitest and Playwright
84
+ integrations, bounded work per commit (large apps no longer freeze), a lighter panel, and the
85
+ injectable library split into three readable scripts. Details, newest first:
86
+
87
+ - **Scale test.** `examples/vite-react/scale.html?rows=N` renders N memoized cells sharing a
88
+ 2,000-item context and a 4 MB typed-array prop; its readout shows the library's overhead and
89
+ the reports skipped by the cap. The e2e suite runs it with 3,000 rows. The panel shows the
90
+ skipped count in the status tooltip and as a banner.
5
91
  - **`npx rerender-lens panel`.** A dependency-free relay (`rerender-lens/relay`) that serves the
6
92
  panel and forwards messages between apps and panels over server-sent events and POST, so the
7
93
  panel works for any app on any origin without the extension or Vite: Next.js, Webpack, a remote
@@ -18,6 +104,38 @@
18
104
  `clearReports`, `expectWithinBudget`.
19
105
  - A second copy of the library (another bundle on the same page) no longer wraps the hook
20
106
  again, which doubled every report.
107
+ - **Bounded work per commit** (large apps froze the page). Deep equality is memoized across the
108
+ components of one commit and gives up on values too large to walk (reported as `different`);
109
+ large Sets compare by identity. Serialization caps every array/object/Map/Set at 100 entries
110
+ (`…+N more`), every report at 20k nodes, treats typed arrays, `ArrayBuffer`, DOM nodes and
111
+ promises as leaves, and defaults to depth 4. A commit reports at most 200 tracked components
112
+ and stops after 25 ms; the rest is counted in `info().truncated` with a one-time warning.
113
+ Source locations are cached per element, the instance registry prunes on growth only, and
114
+ highlight/flash measure all nodes before drawing (at most 100 boxes).
115
+ - Reports are posted on `window` only once something says it listens (the extension's content
116
+ script, or `replay()`), so a page that runs the library without an open panel pays no
117
+ structured clone per report and wakes none of its own `message` listeners. `hello` and
118
+ `clear` still post; the BroadcastChannel and relay paths are unchanged.
119
+ - The injected library (extension) now runs with `includeState: false`; Settings can turn the
120
+ hook/context/state snapshots on per origin. Effect-loop detection no longer flags commits
121
+ caused by discrete input (typing, dragging). The toolbar badge repaints at most every 100 ms.
122
+ - **The panel keeps up.** Summary totals are incremental; the Offenders/Commits/Fixes lists and
123
+ the "best fix" stat update at most every 250 / 500 ms once 200 reports are buffered (the
124
+ tree and the stream stay live); commit analysis is memoized per commit and root causes are
125
+ found by index; each commit keeps at most 500 reports; buffer eviction is one splice per
126
+ frame. The content script sends one batched port message per task instead of one per
127
+ report. The DevTools panel retries the connect handshake with backoff (up to ~90 s) when a
128
+ page loads the library late, and the polling fallback clears the panel once per reset
129
+ instead of on every poll when the page overruns its buffer.
130
+ - The injectable library ships as three vendor scripts (`rerender-lens.core.js`,
131
+ `rerender-lens.engine.js`, `rerender-lens.js`) built by `scripts/build-vendor.mjs`; the
132
+ Playwright helper still gets one concatenated bundle.
133
+ - Removed: per-component notes and mute, share links (`panel.html?report=…`), the Offenders
134
+ column chooser (*Places*, *Last seen*), and the windowed Offenders/Fixes variant above 200 rows.
135
+ Offenders and Fixes always render plain rows; the tree and the stream stay virtualized. The
136
+ panel also drops its protocol-1 fallbacks: protocol 2 is the only one it speaks.
137
+ - Fix: after a navigation the panel's polling fallback stops until the new page answers `info`,
138
+ instead of evaluating into pages without the library every 500 ms.
21
139
 
22
140
  ## 0.3.0
23
141