perf: lazy-load the CodeMirror editor off the playground critical path - #23
Merged
Conversation
The playground entry chunk statically imported CodeMirror, forcing ~365 kB onto the critical path and inflating Total Blocking Time — the largest single lever in the Lighthouse performance score. The editor now loads via dynamic import() after the shell paints, in its own lazy chunk, mirroring how the Three.js renderer already loads. The play entry chunk drops from 372 kB to 7.85 kB (122 kB to 3.3 kB gzip); both heavyweights now load after first paint. editorApi is nullable until the chunk resolves: recompile() captures it once and self-guards, and the user-action handlers (library pick, New, Share) optional- chain, so a click during the ~tens-of-ms load window safely no-ops.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
Lazy-loads the CodeMirror editor in the playground (
/play) so it no longer sits on the initial critical path — via dynamicimport()after first paint, mirroring how the Three.js renderer already loads.Why
/playscored lower than the landing page on Lighthouse mobile.main.tsstatically imported both CodeMirror and the renderer, so the entry chunk carried ~900 kB. A prior change (already onmain) deferred Three.js; this finishes the split by moving CodeMirror into its own lazy chunk.Measured impact (honest A/B, localhost, identical throttling)
Critical-path entry chunk shrinks dramatically:
playentry (critical path)editor(CodeMirror)Lighthouse (mobile, localhost, one run each):
What this does and doesn't do: code-splitting reduces the critical-path download, so it helps FCP / Speed Index (the shell paints before 365 kB of editor JS arrives) — most on real throttled mobile networks. It does not reduce Total Blocking Time, because the editor is still
import()ed immediately at boot and executes right after paint. The overall score was flat on localhost (where downloads are ~instant); the real-network benefit is expected to be a modest FCP/LCP improvement, not a TBT win.Correctness
editorApiis nullable until its chunk resolves:recompile()captures it once (control-flow narrowing survives the intervening calls) and returns early when null.recompile()self-guards so either ordering is safe.Verification
tsc --noEmitpasses; production build succeeds.Reviewer note
Single-file change (
playground/src/main.ts), no behavioral change — only when the editor JS executes. Reasonable to merge as an incremental FCP/Speed-Index improvement with no regression; not a dramatic score jump. If chasing TBT specifically, the lever is reducing/deferring execution (e.g. idle-callback boot), which trades off editor readiness.