feat: performance tracks on by default under vite dev (performanceTracks option) - #379
Merged
Merged
Conversation
…cks option) New `performanceTracks` option (`boolean | PerformanceTracksOptions`, default `true`): under `vite dev` the plugin injects `virtual:solid-performance-tracks` — a module that calls `@solidjs/web/performance-tracks`' enablePerformanceTracks() with the serialized options — ahead of the app's entry: a head-prepended module script for index.html apps (transformIndexHtml), the first import of the generated or authored client entry in start mode. Hydration and the first interaction land on the Chrome Performance panel's Solid tracks without the app enabling them itself. Never on vite build (dev: true and observe builds included), preview, or test mode; skipped with a warning if the installed @solidjs/web lacks the ./performance-tracks subpath. The dev server already writes its Server-Timing metrics, so nothing changes server-side. Tests (examples/start-ssr): dev asserts the import order in the generated entry, the served module, the pre-bundled adapter import, and a browser-level check that the first click paints measure entries with detail.devtools.track; entries asserts the authored-entry transform; prod/observe assert no injection in build output; a new perf-tracks mode covers false, the options form, test mode, an index.html app, and a dev: true build. Co-authored-by: Cursor <cursoragent@cursor.com>
🦋 Changeset detectedLatest commit: d6eb3e9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Chrome Performance panel tracks are on by default under
vite dev. A newperformanceTracksoption controls it; the plugin injects a small virtual module,virtual:solid-performance-tracks, that doesand reaches the page ahead of the app's entry, so hydration and the first interaction are on the timeline without the app calling
enablePerformanceTracks()itself.Why
@solidjs/web/performance-tracks(rc.10) paints Solid's records — re-runs, interactions, holds, async flights, navigations, server-function calls, and the server's ownServer-Timingspans read back — as custom tracks in the Performance panel. Today every app has to wire the enable call into its own entry, before rendering, and remember to strip it for production. The plugin already owns the client entry in start mode and the dev-serve lifecycle everywhere, so it can do that once, correctly, for every Solid 2 app — the same way the diagnostics bridge is wired.Semantics
performanceTracksvite dev(serve)vite build(incl.dev: true,observe: true) / preview / vitesttrue{ minMs, rich, attribution }falsePerformanceTracksOptionsis imported type-only from@solidjs/web/performance-tracks. All three fields are plain data (attributionisAttributionOptions— numbers, booleans, string literals,false, plain objects of those; no functions), so the object isJSON.stringify'd into the module.vite build, by decision: tracks are a dev-server feature. An observe build that wants tracks in production callsenablePerformanceTracks()itself.mode === 'test', vitest) and preview are excluded, mirroring the diagnostics surface'sapply.configResolvedthe plugin reads the app's@solidjs/webpackage.jsonexportsand, if./performance-tracksis missing (unreachable within the^2.0.0-rc.10peer range), warns once and skips the injection instead of leaving an unresolvable import in the entry.@solidjs/web'sserver.tsappends the trace'sServer-Timingmetrics (solid-shell,solid-boundary,solid-invocation) at head commit in dev builds; the adapter reads them back onto theServertrack. Noted in the module comment.@solidjs/web/performance-trackswas already inoptimizeDeps.includeunder serve (fix: rc.10 follow-ups — live server-function address in dev, event-stream preview passthrough, attribution/perf-tracks pre-bundling #374); the virtual module's import resolves through the optimizer, so it shares the app's@solidjs/signalscore (asserted).Start-only vs all apps
All apps, for parity with the diagnostics bridge, which reaches plain
index.htmlapps throughtransformIndexHtmland start-mode apps through the client entry:hydrate()/render()call. (The JSX compiler hoists its own@solidjs/webhelper import above everything; evaluating the runtime module renders nothing, so the ordering that matters holds.)<script type="module" src="/@id/virtual:solid-performance-tracks">injected withhead-prepend— one deliberate deviation from the bridge'shead: this module has an ordering requirement and module scripts execute in document order, so prepending guarantees it evaluates before the app's entry script wherever that sits.Implementation
src/performance-tracks/index.ts(new): option resolution, subpath guard, module codegen, thesolid:performance-tracksplugin (applyserve-only/non-preview/non-test,resolveId/loadfor the virtual id with the same bare-import resolution assist as the bridge,transformIndexHtml).src/index.ts: theperformanceTracksoption + JSDoc,resolvePerformanceTracksOptions, plugin registration,performanceTrackshanded tostartServe.src/ssr/index.ts:startServeinternalperformanceTracksflag resolved inconfigResolved(same gates as the plugin), the import first in both generated entries and prepended in the authored-entrytransform.package.json:@solidjs/webadded to devDependencies (already a peer) so the type-only import compiles; lockfile moves it from the auto-installed-peer slot.#### options.performanceTracks(with the semantics table and a pointer to the Solid 2.0 diagnostics guide's Performance panel section) and a line in the start-mode Dev bullet. Note:diagnosticshas no README option section to mirror; this one follows the shape of the surrounding option sections.Tests (
examples/start-ssr)hydrate(); the served module callsenablePerformanceTracks({}); the module imports the pre-bundled adapter (.vite/deps/@solidjs_web_performance-tracks.js); browser: aPerformanceObserveronmeasureinstalled before the first click sees entries withdetail.devtools.trackGroup === 'Solid'and a track from the adapter's table (Interactions,Propagation,Effects, …).src/entry-client.tsxis served with the import ahead of its own imports andhydrate().track-entry,trackGroup).performanceTracks: false→ no import and the virtual id doesn't resolve; object form →enablePerformanceTracks({"minMs":2,"rich":false});mode: 'test'→ no import; anindex.htmlapp (temp root inside the example) gets the module script in<head>before its entry andfalseinjects nothing; adev: truebuild resolves the dev runtime and carries no injection.Results: start-ssr 626/626 + http-bridge 10/10 + components-warning 11/11 + webworker-warning 12/12; start-client 65/65; start-env 47/47; ssr 12/12 + 8/8; root
pnpm test(vite-8, Cypress) passes;pnpm build,pnpm check(100/100) pass.Public API changes
performanceTracks?: boolean | PerformanceTracksOptionson the plugin'sOptions. Default:true— behaviour change undervite devfor every app: the tracks module is injected andenablePerformanceTracks()runs before the app renders (a no-op withdev: falseand noobserve, where the production runtime is served).falserestores the previous behaviour. No change to build output, preview, or test mode.PerformanceTracksOption = boolean | PerformanceTracksOptionsappears in the emitted declarations (the option's type);PerformanceTracksOptionsitself is@solidjs/web/performance-tracks' type, not re-exported../performance-trackssubpath), reachable only outside the peer range.