Repository navigation
Bench: Declare the React renderer dependency the harnesses rely on - #35686
valentinpalkovic merged 2 commits into
Conversation
WalkthroughThe benchmark tooling now resolves React renderer modules from the installed ChangesReact renderer resolution
Sequence Diagram(s)sequenceDiagram
participant BenchmarkLoader
participant StorybookReactSource
participant ErrorNormalizer
BenchmarkLoader->>StorybookReactSource: Resolve componentManifest directory
StorybookReactSource-->>BenchmarkLoader: Return renderer source path
BenchmarkLoader->>StorybookReactSource: Import renderer module
StorybookReactSource-->>BenchmarkLoader: Return module or import error
BenchmarkLoader->>ErrorNormalizer: Normalize import error
ErrorNormalizer-->>BenchmarkLoader: Return contextual error
Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
Comment |
ca429f9 to
0717d83
Compare
0717d83 to
d7229f7
Compare
d7229f7 to
ead1f00
Compare
The React harnesses measure the renderer's own extraction code, so they import it from source. That reach was a hardcoded ../../../ into code/renderers/react with no dependency behind it: nothing in the workspace graph recorded the coupling, and it worked only because a full install happens to put the renderer's own dependencies where its source can find them. Declare @storybook/react in scripts and anchor on the resolved package instead. The path now moves with the package, and the two ways this fails say what to do rather than naming a file the harness never mentioned - one for a checkout with no renderer source, one for a missing code/core build. Adds one workspace descriptor to the lockfile; no new resolutions.
@storybook/react declares a non-optional `storybook: workspace:^` peer. Adding the renderer to scripts without providing it left the peer unmet, and CI's --frozen-lockfile install then wanted to write a resolution the committed lockfile did not have. Declaring it is right on its own terms: the renderer source the React harnesses load imports storybook/internal/*, so the bench already depends on core at runtime and only ever worked because a full install put it in reach.
ead1f00 to
babd0f6
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/bench/PERF-METHODOLOGY.md (1)
29-31: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCorrect the latency-metric definition.
Line 31 says that every latency metric records a median for cold extractions. The same sentence then defines warm extraction separately. This conflicts with the warm metric in Line 14 and can cause readers to apply the cold sampling rule to warm measurements.
Suggested wording
- Every latency metric records a median for cold extractions. We need to make sure that these are triggered in fresh processes, so there are n samples that come from n separate spawns, while warm extracts takes the median of the per-save durations inside one run. + Every latency metric records a median. Cold extraction uses N samples from N separate spawns. Warm extraction uses the median of per-save durations inside one run.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/bench/PERF-METHODOLOGY.md` around lines 29 - 31, Clarify the “Median-of-N for latency” definition in PERF-METHODOLOGY.md so the median across fresh process spawns applies only to cold extraction metrics, while warm extraction metrics use the median of per-save durations within a single run. Remove or revise the wording that says every latency metric records a cold-extraction median, preserving the definitions established for warm measurements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@scripts/bench/PERF-METHODOLOGY.md`:
- Around line 29-31: Clarify the “Median-of-N for latency” definition in
PERF-METHODOLOGY.md so the median across fresh process spawns applies only to
cold extraction metrics, while warm extraction metrics use the median of
per-save durations within a single run. Remove or revise the wording that says
every latency metric records a cold-extraction median, preserving the
definitions established for warm measurements.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5b676abb-a866-48af-8e0d-6f17ab8cca7e
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (4)
scripts/bench/PERF-METHODOLOGY.mdscripts/bench/docgen-shared/react-renderer-module.test.tsscripts/bench/docgen-shared/react-renderer-module.tsscripts/package.json
🚧 Files skipped from review as they are similar to previous changes (3)
- scripts/bench/docgen-shared/react-renderer-module.test.ts
- scripts/package.json
- scripts/bench/docgen-shared/react-renderer-module.ts
Last of the docgen bench stack. Closes the one real coupling problem the suite had left.
The problem
The React harnesses measure the renderer's own extraction code, so they import it from source rather than through the published surface. That reach was a hardcoded relative path with no dependency behind it:
scripts/package.jsondeclared exactly oneworkspace:*dependency and it waseslint-plugin-storybook, so nothing in the workspace graph recorded thatscriptsneeds the React renderer at all.It works today by accident. The renderer's source imports
storybook/internal/common, andstorybookis apeerDependencyof@storybook/react- so the bench only runs because a full install happens to put the renderer's own dependencies somewhere its source can reach from a process launched out ofscripts/. On a partial install it fails like this:Nothing in that message mentions the bench, and nothing tells you what to do.
The change
Declare
@storybook/react": "workspace:*"inscripts, and anchor on the resolved package instead of a relative path. The path now moves with the package, and the coupling is visible to Nx and to anyone reading the manifest.Both failure modes now say what to do instead of naming a file the harness never mentioned:
code/corebuild becomesRun \yarn nx compile core` and try again, with Node's original error preserved as the cause. This is the one that actually bites - the renderer importsstorybook/internal/*, which resolves tocode/core'sdist/`, so a fresh checkout hits it immediately.Verification
cold pass: 35ms→29ms, same output shape.code/core/dist.yarn dedupe --checkclean. The lockfile gains exactly one line, the workspace descriptor; no new resolutions, nothing re-resolved.What this does not do
It does not unblock a react-docgen version pair. Declaring the dependency makes the source reachable, but the renderer still imports
react-docgenby bare specifier, so pointing it at a second install would need a module resolution hook registered in the child. Noted inPERF-METHODOLOGY.mdso the next person does not rediscover it.Considered and rejected: moving the whole suite into
@storybook/docgen-harness. The workspace shares one lockfile, so there are no duplicate installs to reclaim -vue-docgen-apiis declared by three workspaces and resolves to one copy. Compodoc would get worse, since docgen-harness deliberately commits capturedcompodoc-input.jsonfixtures instead of depending on it. And the two harnesses pull in opposite directions: docgen-harness wants real framework types for correctness, the bench ships a fake minimal@angular/coreso cold time does not move when Angular is upgraded.Manual testing
Expect a cold pass and one save timing, identical in shape to before the change.
To see the coupling actually being resolved rather than guessed, check that the anchor is the package rather than a relative path:
To see the error redirect that motivates the change, hide the core build and re-run the engine:
Expect
Run `yarn nx compile core` and try againwith Node's original resolution error kept as the cause, rather than a bareERR_MODULE_NOT_FOUNDnaming astorybook/distpath the harness never mentioned.