Hub vite server crashes on dep-scan: "virtual:pwa-register imported by tasks-app/main.ts could not be resolved" #74

Open
opened 2026-05-24 15:32:28 +00:00 by padreug · 0 comments
Owner

Symptom

On pnpm run dev:all (or any fresh hub pnpm run dev with a cold
node_modules/.vite-hub/ cache), the hub vite server crashes:

[hub] Error: The following dependencies are imported but could not be resolved:
[hub]   virtual:pwa-register (imported by .../src/tasks-app/main.ts)
[hub]     at .../vite/dist/node/chunks/dep-Dq2t6Dq0.js:14849:15

The hub never starts. Standalone vite servers (tasks, activities,
wallet, …) start fine because each has its own vite.<app>.config.ts
with VitePWA(...) registered.

Root cause

Vite's optimizeDeps scanner walks all *.html files in the project
root by default. The repo root has 9 standalone HTML entries
(tasks.html, activities.html, wallet.html, etc.) in addition to
index.html. Each standalone HTML points at src/<app>-app/main.ts,
all of which begin with:

import { registerSW } from 'virtual:pwa-register'

virtual:pwa-register is supplied by vite-plugin-pwa. Per
commit 0a07691 (fix(hub): drop hub PWA install to unblock standalone PWAs (closes #41)) the hub's vite.config.ts
intentionally omits VitePWA — the hub is a launcher, not a PWA. So
when the hub's scanner crawls tasks.htmltasks-app/main.ts
virtual:pwa-register, resolution fails and Vite refuses to start
the dev server.

The bug has been latent since #41 shipped; it only surfaces when
the hub's .vite-hub/ cache is cold (e.g. fresh worktree install,
vite --force, dep version change). Once the cache is warm, the
scanner skips the standalone entries and the hub starts cleanly.

Reproduction

cd ~/dev/webapp/<some-worktree-off-dev>
rm -rf node_modules/.vite-hub
pnpm run dev
# → hub crashes on virtual:pwa-register

Or:

cd ~/dev/webapp/<fresh-worktree>
pnpm install --frozen-lockfile
pnpm run dev:all
# → [hub] crashes; standalones start fine

Proposed fix

Constrain the hub's optimizeDeps.entries to just index.html.
The hub serves the launcher page; the standalones each run on their
own vite port via dev:<app> and don't need to be scanned by the
hub.

// vite.config.ts
export default defineConfig(({ mode }) => ({
  cacheDir: 'node_modules/.vite-hub',
  server: { port: 5173, strictPort: true },
  optimizeDeps: {
    // The hub is the launcher; standalone *.html entries (tasks.html,
    // wallet.html, etc.) belong to their own vite servers and don't
    // need to be pre-bundled here. Scoping the scan to index.html
    // avoids the `virtual:pwa-register` resolution failure when the
    // dep-cache is cold (the hub intentionally omits VitePWA per #41).
    entries: ['index.html'],
  },
  plugins: [...]
}))

One-liner functionally, two with the comment. No standalone config
changes needed.

Why this is the right fix (not "add VitePWA to the hub")

Re-adding VitePWA to the hub would resurface the #41 install-prompt
shadowing — the hub at / claiming SW scope blocks Chrome from
offering installs for the path-mounted standalones at /tasks/,
/market/, etc. The optimizeDeps scope fix keeps the hub's intent
intact while preventing the cold-cache crash.

Out of scope

  • Removing the per-standalone dev:<app> scripts. They're needed
    for subdomain-style standalone serving and isolated port
    binding.
  • Combining the hub + standalones into one vite server. Tried
    before; per #41 the SW-scope collision makes it worse, not
    better.

Test plan

  • rm -rf node_modules/.vite-hub && pnpm run dev → hub
    starts on :5173 without the virtual:pwa-register error.
  • pnpm run dev:all cold-starts cleanly; all 9 vite servers
    come up.
  • Production pnpm run build and pnpm run build:demo
    remain unaffected (the optimizeDeps flag is dev-only).
  • Standalone PWA installs still work in dev (e.g.
    localhost:5181/activities.html offers Install).
## Symptom On `pnpm run dev:all` (or any fresh hub `pnpm run dev` with a cold `node_modules/.vite-hub/` cache), the hub vite server crashes: ``` [hub] Error: The following dependencies are imported but could not be resolved: [hub] virtual:pwa-register (imported by .../src/tasks-app/main.ts) [hub] at .../vite/dist/node/chunks/dep-Dq2t6Dq0.js:14849:15 ``` The hub never starts. Standalone vite servers (tasks, activities, wallet, …) start fine because each has its own `vite.<app>.config.ts` with `VitePWA(...)` registered. ## Root cause Vite's `optimizeDeps` scanner walks all `*.html` files in the project root by default. The repo root has 9 standalone HTML entries (`tasks.html`, `activities.html`, `wallet.html`, etc.) in addition to `index.html`. Each standalone HTML points at `src/<app>-app/main.ts`, all of which begin with: ```ts import { registerSW } from 'virtual:pwa-register' ``` `virtual:pwa-register` is supplied by `vite-plugin-pwa`. Per **commit `0a07691` (`fix(hub): drop hub PWA install to unblock standalone PWAs (closes #41)`)** the hub's `vite.config.ts` intentionally omits VitePWA — the hub is a launcher, not a PWA. So when the hub's scanner crawls `tasks.html` → `tasks-app/main.ts` → `virtual:pwa-register`, resolution fails and Vite refuses to start the dev server. The bug has been latent since #41 shipped; it only surfaces when the hub's `.vite-hub/` cache is cold (e.g. fresh worktree install, `vite --force`, dep version change). Once the cache is warm, the scanner skips the standalone entries and the hub starts cleanly. ## Reproduction ```bash cd ~/dev/webapp/<some-worktree-off-dev> rm -rf node_modules/.vite-hub pnpm run dev # → hub crashes on virtual:pwa-register ``` Or: ```bash cd ~/dev/webapp/<fresh-worktree> pnpm install --frozen-lockfile pnpm run dev:all # → [hub] crashes; standalones start fine ``` ## Proposed fix Constrain the hub's `optimizeDeps.entries` to just `index.html`. The hub serves the launcher page; the standalones each run on their own vite port via `dev:<app>` and don't need to be scanned by the hub. ```ts // vite.config.ts export default defineConfig(({ mode }) => ({ cacheDir: 'node_modules/.vite-hub', server: { port: 5173, strictPort: true }, optimizeDeps: { // The hub is the launcher; standalone *.html entries (tasks.html, // wallet.html, etc.) belong to their own vite servers and don't // need to be pre-bundled here. Scoping the scan to index.html // avoids the `virtual:pwa-register` resolution failure when the // dep-cache is cold (the hub intentionally omits VitePWA per #41). entries: ['index.html'], }, plugins: [...] })) ``` One-liner functionally, two with the comment. No standalone config changes needed. ## Why this is the right fix (not "add VitePWA to the hub") Re-adding VitePWA to the hub would resurface the #41 install-prompt shadowing — the hub at `/` claiming SW scope blocks Chrome from offering installs for the path-mounted standalones at `/tasks/`, `/market/`, etc. The optimizeDeps scope fix keeps the hub's intent intact while preventing the cold-cache crash. ## Out of scope - Removing the per-standalone `dev:<app>` scripts. They're needed for subdomain-style standalone serving and isolated port binding. - Combining the hub + standalones into one vite server. Tried before; per #41 the SW-scope collision makes it worse, not better. ## Test plan - [ ] `rm -rf node_modules/.vite-hub && pnpm run dev` → hub starts on `:5173` without the `virtual:pwa-register` error. - [ ] `pnpm run dev:all` cold-starts cleanly; all 9 vite servers come up. - [ ] Production `pnpm run build` and `pnpm run build:demo` remain unaffected (the `optimizeDeps` flag is dev-only). - [ ] Standalone PWA installs still work in dev (e.g. `localhost:5181/activities.html` offers Install).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/webapp#74
No description provided.