You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The extension is published as a collection of raw JavaScript files (src/extension.js, src/remoteUrl.js) plus a node_modules tree at runtime. The VS Code bundling guide explicitly recommends bundling because:
Loading 100 small files is much slower than loading one large file.
More importantly, only bundled extensions can run in VS Code for the Web (github.dev, vscode.dev) — when VS Code runs in the browser, it loads exactly one file per extension.
Request
Current experience
The published VSIX contains the source tree as-is, plus any runtime dependencies under node_modules
Activation is slower than necessary because VS Code must resolve and load each file individually
The extension cannot run in VS Code for the Web because there is no single bundled entry point
Desired experience
A single bundled dist/extension.js is produced at build time
Activation is faster because only one file is loaded
The same bundle is reused as the foundation for a future web-extension build (tracked in a separate issue)
Source files (src/), build configs, and node_modules are excluded from the published VSIX
Acceptance criteria
The extension is bundled into dist/extension.js using a configured bundler
package.jsonmain points to the bundled output (./dist/extension.js)
A vscode:prepublish script exists and runs the production bundle build
Source maps are generated (hidden source maps for production, full for development)
node_modules, src/, and bundler config files are excluded from the VSIX via .vscodeignore
The bundled VSIX is meaningfully smaller than the current published artifact (size to be measured)
Existing functionality (Explorer context menu, custom view, keybindings) is unchanged
The codebase is plain JavaScript with JSDoc, so esbuild's minimal configuration is sufficient. Webpack would add complexity without proportional value.
Build script: Use a small esbuild.js build script (per the VS Code bundling guide example) that supports --production and --watch flags.
Entry point:src/extension.js → bundled to dist/extension.js. The vscode module must be marked external (it is provided by the runtime, not bundled).
Platform target: Start with platform: 'node' to preserve current behavior. A follow-up issue will introduce a webworker target for web-extension support.
Source maps:sourcemap: !production. Production builds use hidden source maps (--devtool hidden-source-map equivalent in esbuild) so stack traces are decodable but the .js.map is not advertised in the source.
The existing package / publish scripts are renamed to package:vsix / publish:vsix to avoid colliding with the bundling package script. The CI workflow currently calls vsce package directly; verify it still works after this rename or invoke npm run package:vsix.
Adding src/** removes the source files from the VSIX. This is intentional — the bundled dist/extension.js is now the sole runtime artifact. The resources/ folder (icons used by package.json contributions) must stay included.
Coordination with web extension support: A separate issue will add a browser entry point and a webworker-targeted build. This issue establishes the bundling foundation; web-extension support builds on it.
Coordination with build workflow: The CI workflow (.github/workflows/build-vscode-extension.yml) calls npx vsce package after npm ci. With vscode:prepublish defined, vsce will run the bundle automatically — no workflow changes are strictly required, but the VSIX verification step (#4) should be updated to expect dist/extension.js instead of src/extension.js.
Implementation plan
Build configuration
Add esbuild to devDependencies
Add esbuild.js build script supporting --production and --watch flags, with vscode marked external
Update package.jsonmain to ./dist/extension.js
Update package.jsonscripts to add compile, watch, package, vscode:prepublish and rename existing package/publish to package:vsix/publish:vsix
Project hygiene
Add dist/ to .gitignore
Update .vscodeignore to exclude src/, esbuild.js, eslint.config.js, package-lock.json, tsconfig*.json
The extension is published as a collection of raw JavaScript files (
src/extension.js,src/remoteUrl.js) plus anode_modulestree at runtime. The VS Code bundling guide explicitly recommends bundling because:More importantly, only bundled extensions can run in VS Code for the Web (github.dev, vscode.dev) — when VS Code runs in the browser, it loads exactly one file per extension.
Request
Current experience
node_modulesDesired experience
dist/extension.jsis produced at build timesrc/), build configs, andnode_modulesare excluded from the published VSIXAcceptance criteria
dist/extension.jsusing a configured bundlerpackage.jsonmainpoints to the bundled output (./dist/extension.js)vscode:prepublishscript exists and runs the production bundle buildnode_modules,src/, and bundler config files are excluded from the VSIX via.vscodeignoreTechnical decisions
Bundler choice: esbuild over webpack.
ts-loaderThe codebase is plain JavaScript with JSDoc, so esbuild's minimal configuration is sufficient. Webpack would add complexity without proportional value.
Build script: Use a small
esbuild.jsbuild script (per the VS Code bundling guide example) that supports--productionand--watchflags.Entry point:
src/extension.js→ bundled todist/extension.js. Thevscodemodule must be marked external (it is provided by the runtime, not bundled).Platform target: Start with
platform: 'node'to preserve current behavior. A follow-up issue will introduce awebworkertarget for web-extension support.Source maps:
sourcemap: !production. Production builds use hidden source maps (--devtool hidden-source-mapequivalent in esbuild) so stack traces are decodable but the.js.mapis not advertised in the source.package.jsonscripts:{ "scripts": { "lint": "eslint src", "compile": "node esbuild.js", "watch": "node esbuild.js --watch", "package": "node esbuild.js --production", "vscode:prepublish": "npm run package", "package:vsix": "vsce package", "publish:vsix": "vsce publish" } }The existing
package/publishscripts are renamed topackage:vsix/publish:vsixto avoid colliding with the bundlingpackagescript. The CI workflow currently callsvsce packagedirectly; verify it still works after this rename or invokenpm run package:vsix.Updated
.vscodeignore:Important
Adding
src/**removes the source files from the VSIX. This is intentional — the bundleddist/extension.jsis now the sole runtime artifact. Theresources/folder (icons used bypackage.jsoncontributions) must stay included.Coordination with web extension support: A separate issue will add a
browserentry point and awebworker-targeted build. This issue establishes the bundling foundation; web-extension support builds on it.Coordination with build workflow: The CI workflow (
.github/workflows/build-vscode-extension.yml) callsnpx vsce packageafternpm ci. Withvscode:prepublishdefined,vscewill run the bundle automatically — no workflow changes are strictly required, but the VSIX verification step (#4) should be updated to expectdist/extension.jsinstead ofsrc/extension.js.Implementation plan
Build configuration
esbuildtodevDependenciesesbuild.jsbuild script supporting--productionand--watchflags, withvscodemarked externalpackage.jsonmainto./dist/extension.jspackage.jsonscriptsto addcompile,watch,package,vscode:prepublishand rename existingpackage/publishtopackage:vsix/publish:vsixProject hygiene
dist/to.gitignore.vscodeignoreto excludesrc/,esbuild.js,eslint.config.js,package-lock.json,tsconfig*.jsonresources/and the to-be-addedmedia/(Add screenshots and animated demo to README for Marketplace #17) andCHANGELOG.md(Enrich Marketplace metadata in package.json (keywords, galleryBanner, bugs, homepage, categories) #15) remain includedCI
build-vscode-extension.yml) still produces a valid VSIX after the changeextension/dist/extension.jsinstead ofextension/src/extension.jsValidation
npm run packagelocally and confirmdist/extension.jsis produced and minifiedvsce packageand inspect the VSIX contents —src/andnode_modules/must be absentDocumentation
README.mdDevelopment section with the newnpm run watchworkflow