Skip to content

feat(hub): let buildHub bake statics/frames outside the hub base (sibling deploy layout) #353

Description

@antfubot

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:

  1. 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.
  2. 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.tsresolveOutPath / 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions