Sccarda/webview file size#3356
Draft
ScottCarda-MS wants to merge 4 commits into
Draft
Conversation
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.
Reduce VS Code webview bundle size
Summary
The Bloch sphere widget pulled three.js into the
shared
webview.jsbundle, growing it from ~3 MB to ~4.4 MB. That bundle isloaded eagerly for every Q# output panel (histograms, circuit diagrams,
resource estimates, documentation, etc.), so every panel paid for three.js
even though only the Bloch sphere needs it. The chemistry
MoleculeViewerwidget was bundling 3Dmol into the same bundle in the
same way, despite never being used in the VS Code webview at all.
This PR removes those heavy libraries from the eagerly-loaded bundle by
lazy-loading them, and additionally enables minification for the VS Code
build (which previously never minified its output).
Result: the eagerly-loaded
webview.jsdrops from ~4.4 MB to 0.56 MB(−87%). three.js is now downloaded only when a user actually opens a Bloch
sphere panel.
Motivation
webview.jsis shared by all Q# webview panels and is loaded on first use ofany of them. Heavy, rarely-used 3D libraries do not belong in that shared
bundle — they should load on demand, only when their feature is opened.
Changes
1. Root cause: static barrel exports
qsharp-lang/uxhas a single barrel file (ux/index.ts) that re-exportseverything, including the 3D widgets:
Both
webview.tsx(all panels) andeditor.tsx(circuit editor) import fromthis barrel. Even though neither uses
BlochSphereorMoleculeVieweratruntime in most cases, esbuild must include the full module graph of every
re-export — including the 3D libraries — because it cannot know at build time
which exports will be used.
2. Move heavy exports to dedicated subpath entries
BlochSphereandMoleculeViewerwere removed from the main barrel andplaced behind their own package export subpaths:
Consumers that actually need those widgets import from the subpath directly
(
qsharp-lang/ux/bloch,qsharp-lang/ux/chem).3. Lazy-load
BlochSpherein the webviewwebview.tsxnow uses a dynamic import (Preactlazy+Suspense):4. esbuild code-splitting for
webview.tsxFor the dynamic import to produce a separate file, esbuild's
splittingfeature must be enabled. The VS Code build (
vscode/build.mjs) now buildswebview.tsxas an ES module with splitting turned on:The other two entry points (
editor.tsxand the learning webview client)remain CommonJS — no change to their behaviour.
5.
<script type="module">in the webview HTMLBecause
webview.jsis now an ES module, the<script>tag in theextension's webview HTML was updated from:
to:
6. Minify the VS Code bundles
The VS Code esbuild build previously never minified its output — unlike
the playground, which minifies behind a (rarely-used)
--releaseflag.Minification is now enabled for normal one-shot builds (CI and
build.py)but stays off during watch mode, so iterative development keeps fast
rebuilds and readable stack traces:
Linked source maps are still emitted for minified builds, so production stack
traces remain debuggable.
Results
"Lazy-load" is the barrel/code-splitting work (steps 1–5); "+ minify" adds
step 6. All numbers are bundle sizes on disk.
webview.js(loaded for every panel)editor.js(circuit editor)chunks/bloch-*.js(lazy)chunks/chunk-*.js(shared, eager)The Bloch sphere's 3D engine is now both minified and only downloaded when
a user actually opens a Bloch sphere panel, rather than on every extension
startup. Minification also applies to the extension-host bundles
(
extension.js, workers), which were never minified before either.Testing
Full build passes (
python ./build.py --no-check --no-test --npm --vscode --play),including all three VS Code typechecks (main / view / learning).
Manually verified in the Extension Development Host that the Bloch sphere,
circuit editor, and state visualizer panels all render correctly.
Confirmed three.js and 3Dmol are absent from the eagerly-loaded bundle:
Confirmed linked source maps are still emitted alongside the minified
bundles.
Risks / Notes
fetches its chunk on demand, a small one-time delay in exchange for faster
startup of every other panel.
BlochSphereorMoleculeViewerfromqsharp-lang/uxmust switch toqsharp-lang/ux/blochor
qsharp-lang/ux/chem. All in-repo consumers have been updated.extension.js,workers) are minified for the first time; activation was sanity-checked in
the Extension Development Host.
Files Changed
source/npm/qsharp/ux/index.tsBlochSphereandMoleculeViewerre-exportssource/npm/qsharp/package.json./ux/blochand./ux/chemsubpath exportssource/vscode/build.mjswebview.tsxinto a separate ESM + code-splitting build target; enable minification for non-watch buildssource/vscode/src/webview/webview.tsximport()+lazy/SuspenseforBlochSpheresource/vscode/src/webviewPanel.ts<script type="module">to load the ESM bundlesource/playground/src/main.tsxBlochSpherefromqsharp-lang/ux/blochsubpathsource/widgets/js/index.tsxMoleculeViewerfromqsharp-lang/ux/chemsubpath