Follow-up to #347 / #349.
buildHub({ context }) (#349) lets a host that assembled + mounted its own hub context hand it to the baker. Vite DevTools tried to adopt it to delete its hand-rolled build-static.ts, but hit a layout assumption: buildHub bakes the whole hub as one subtree under a single base, and Vite DevTools serves its devframes and assets as root-level siblings of the hub base.
The blocker
buildHub's resolveOutPath throws DF8006 for any URL base that doesn't start with the hub base:
const resolveOutPath = (urlBase) => {
if (!urlBase.startsWith(base)) throw diagnostics.DF8006({ urlBase, base })
return resolve(outDir, urlBase.slice(base.length))
}
It's applied to every ctx.views.buildStaticDirs entry (copyBuildStatics) and every served frame base (writeConnectionMetas). That's fine when every devframe mounts under the hub base (/__devframes/<id>/), as the built-in examples do.
Vite DevTools' layout is different. The hub UI + endpoints live at /__devtools/, but:
| Surface |
Base at serve time |
Hub UI + endpoints (__connection.json, __rpc-dump/, __index.json, __renderers/) |
/__devtools/ |
| Inspect devframe SPA |
/__devframes_plugin_inspect/ |
| Messages devframe SPA |
/__devframes_plugin_messages/ |
| Vendored launcher assets |
/__devtools-assets/ |
The devframes mount at devframe's own default hosted base (/__<id>/, via resolveBasePath), and the assets at a dedicated root path — all siblings of /__devtools/, not children. So buildHub({ context, base: '/__devtools/' }) throws DF8006 on the first sibling static dir, and base: '/' would misplace the hub's own endpoints (the kit client fetches them from /__devtools/, baked into the app's injected bootstrap).
Either base choice fails, so buildHub can't currently bake this context — Vite DevTools keeps shadowing the baker (now only the RPC-dump + resolveFrom bits are shared).
Why the layout is like this
The hub base is a protocol namespace (its connection meta, WS, dump, renderer modules, index), deliberately distinct from where each integration's SPA and assets are served. A host may want the hub at /__devtools/ while devframes keep their own top-level bases (so a devframe SPA URL is stable and independent of which hub mounts it). This is a legitimate deploy shape, not a Vite-DevTools quirk.
Request
Let buildHub bake a context whose statics/frames live outside the hub base — a deploy-root layout where the hub base and the devframe/asset bases are siblings under a common deploy root. Concretely, one of:
- A
root/deployBase option distinct from the hub base: outDir maps to the deploy root, absolute URL bases resolve against it (resolve(outDir, stripLeadingSlash(urlBase))), and the hub's own artifacts still write under base within it. Then resolveOutPath only needs each urlBase to be within the deploy root (i.e. absolute), not within the hub base — no DF8006 for siblings.
- Or relax
resolveOutPath so a urlBase outside base maps to outDir's parent by its absolute path (with the hub subtree still at <outDir>), covering the sibling case without a new option.
writeConnectionMetas/writeHubIndex already read ctx.frames + ctx.views.buildStaticDirs, so per-frame metas and the index would follow automatically once the out-path resolution allows sibling bases.
This is the last gap before Vite DevTools can delete build-static.ts and bake purely through buildHub.
Context
buildHub: packages/hub/src/node/build.ts — resolveOutPath / copyBuildStatics / writeConnectionMetas
- Downstream builder we want to retire:
vitejs/devtools packages/core/src/node/build-static.ts
- Downstream mount bases: hub
/__devtools/; devframes at resolveBasePath = /__<id>/; assets at /__devtools-assets/
Created with the help of an agent.
Follow-up to #347 / #349.
buildHub({ context })(#349) lets a host that assembled + mounted its own hub context hand it to the baker. Vite DevTools tried to adopt it to delete its hand-rolledbuild-static.ts, but hit a layout assumption:buildHubbakes the whole hub as one subtree under a singlebase, and Vite DevTools serves its devframes and assets as root-level siblings of the hub base.The blocker
buildHub'sresolveOutPaththrowsDF8006for any URL base that doesn't start with the hubbase:It's applied to every
ctx.views.buildStaticDirsentry (copyBuildStatics) and every served frame base (writeConnectionMetas). That's fine when every devframe mounts under the hub base (/__devframes/<id>/), as the built-in examples do.Vite DevTools' layout is different. The hub UI + endpoints live at
/__devtools/, but:__connection.json,__rpc-dump/,__index.json,__renderers/)/__devtools//__devframes_plugin_inspect//__devframes_plugin_messages//__devtools-assets/The devframes mount at devframe's own default hosted base (
/__<id>/, viaresolveBasePath), and the assets at a dedicated root path — all siblings of/__devtools/, not children. SobuildHub({ context, base: '/__devtools/' })throwsDF8006on the first sibling static dir, andbase: '/'would misplace the hub's own endpoints (the kit client fetches them from/__devtools/, baked into the app's injected bootstrap).Either
basechoice fails, sobuildHubcan't currently bake this context — Vite DevTools keeps shadowing the baker (now only the RPC-dump +resolveFrombits are shared).Why the layout is like this
The hub base is a protocol namespace (its connection meta, WS, dump, renderer modules, index), deliberately distinct from where each integration's SPA and assets are served. A host may want the hub at
/__devtools/while devframes keep their own top-level bases (so a devframe SPA URL is stable and independent of which hub mounts it). This is a legitimate deploy shape, not a Vite-DevTools quirk.Request
Let
buildHubbake a context whose statics/frames live outside the hubbase— a deploy-root layout where the hub base and the devframe/asset bases are siblings under a common deploy root. Concretely, one of:root/deployBaseoption distinct from the hubbase:outDirmaps to the deploy root, absolute URL bases resolve against it (resolve(outDir, stripLeadingSlash(urlBase))), and the hub's own artifacts still write underbasewithin it. ThenresolveOutPathonly needs eachurlBaseto be within the deploy root (i.e. absolute), not within the hub base — noDF8006for siblings.resolveOutPathso aurlBaseoutsidebasemaps tooutDir's parent by its absolute path (with the hub subtree still at<outDir>), covering the sibling case without a new option.writeConnectionMetas/writeHubIndexalready readctx.frames+ctx.views.buildStaticDirs, so per-frame metas and the index would follow automatically once the out-path resolution allows sibling bases.This is the last gap before Vite DevTools can delete
build-static.tsand bake purely throughbuildHub.Context
buildHub:packages/hub/src/node/build.ts—resolveOutPath/copyBuildStatics/writeConnectionMetasvitejs/devtoolspackages/core/src/node/build-static.ts/__devtools/; devframes atresolveBasePath=/__<id>/; assets at/__devtools-assets/Created with the help of an agent.