Skip to content

perf: trim destyler preload and unblock playground first paint - #1

Merged
elonehoo merged 11 commits into
nextfrom
perf/trim-destyler-preload
Sep 3, 2026
Merged

elonehoo merged 11 commits into
nextfrom
perf/trim-destyler-preload

Conversation

@elonehoo

@elonehoo elonehoo commented Sep 2, 2026 •

Copy link
Copy Markdown
Member

Summary

Playground boot was blocked on importing every Destyler package sequentially, then waiting for Monaco + Volar (TypeScript @latest from jsDelivr) before hiding the splash. The preview iframe also lived in a display:none Splitter slot and was appendChild’d into the visible panel, which reloaded it; a fake 500ms timer then marked it “loaded”.

This PR keeps Destyler component APIs, in-browser SFC compile, and framework switching unchanged. The default Vue checkbox + counter demo still only needs @destyler/checkbox + @destyler/vue.

What changed

  1. Trim destyler import map / preload

    • Scan playground files for from '…' / import('…') (and export-from).
    • Import map + preload only those Destyler packages, plus the active framework adapter and framework runtime (vue / react / …).
    • Other Destyler packages are lazy-loaded when the compiler / getFile / require path needs them (Vue/React/Solid/Svelte).
    • Remaining preloads use a bounded Promise.all pool (concurrency 8). Failures log and do not stall boot.
    • Concrete Destyler versions stay pinned on esm.sh (@x.y.z); latest is still unpinned.
  2. Unblock first paint

    • Hide “Loading Playground…” after the shell is painted and iframe srcdoc is assigned.
    • Do not wait for Monaco language service.
    • setupLanguageService is deferred via requestIdleCallback (timeout 2s).
    • Only the active framework Monaco worker is dynamically imported.
    • Worker TypeScript CDN version is pinned to 5.6.2 instead of typescript@latest.
  3. Iframe

    • Reparent editor/preview into #editor-panel / #preview-panel before assigning srcdoc, so the iframe is not moved while hidden (avoids reload).
    • Use iframe.onload instead of a 500ms isIframeLoaded timer.

Why

Default boot was paying for ~40 unused Destyler packages, serial await import(), Volar/TS worker init, and an extra iframe navigation. First paint and first preview should only pay for Vue + checkbox + the shell.

Test plan

  • Default Vue playground: splash hides quickly; checkbox + counter render.
  • Add import * as dialog from '@destyler/dialog' in App.vue and use it — preview hot-updates without a full Destyler catalog preload.
  • Switch Vue → React → Solid → Svelte; each default checkbox demo still works.
  • Select a concrete Destyler version (not latest) and confirm esm.sh URLs include @<version>.
  • Editor still gets Vue completions after idle (Volar deferred, not removed).
  • Resize splitter / reload page: preview iframe does not flash a double load.

Remaining caveats

  • First Destyler import of a package that was not in the initial scan still pays a CDN round-trip (lazy load).
  • Monaco/Volar is ready slightly after the editor appears; go-to-definition / diagnostics may lag on first paint.
  • latest Destyler (and framework CORE_IMPORTS on esm.sh) remain unpinned until a version is chosen.
  • Splitter still renders Astro children into a hidden source node, then moves them once; we only changed when that move happens (before srcdoc).
  • Worker TypeScript pin (5.6.2) is independent of whatever typescript@latest would have resolved to on jsDelivr.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Scan playground sources for import specifiers and build a trimmed destyler
import map instead of fetching every component and shared package. Remaining
preloads run with bounded concurrency, and destyler packages added later are
lazy-loaded on demand.
Language service no longer blocks editor creation; it starts on idle.
Framework workers are dynamically imported so Vue boot does not fetch
React/Solid/Svelte workers, and TypeScript is pinned instead of @latest.
Move the preview iframe into the visible panel before assigning srcdoc so
appendChild does not reload it. Mark the iframe loaded via onload instead
of a 500ms timer, and hide the overlay once the shell/srcdoc is ready
without waiting for Monaco.
@elonehoo elonehoo closed this Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026 •

Copy link
Copy Markdown

🧹 PR Preview has been removed

The Zeabur preview service for this PR has been deleted.

@elonehoo elonehoo reopened this Sep 3, 2026
@elonehoo elonehoo closed this Sep 3, 2026
@elonehoo elonehoo reopened this Sep 3, 2026
@elonehoo elonehoo closed this Sep 3, 2026
@elonehoo elonehoo reopened this Sep 3, 2026
@elonehoo
elonehoo merged commit f2d940e into next Sep 3, 2026
2 checks passed
@elonehoo
elonehoo deleted the perf/trim-destyler-preload branch September 3, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant