Skip to content

Examples E2E: on a cold Vite cache, parallel pages miss the dep-optimizer reload and render blank (hidden by retries) #1628

Open

Description

@FNDEVVE

With an empty node_modules/.vite, the first dev load of an example discovers dependencies late (@effect/platform-browser, clsx, effect/http, effect/persistence, parse5), and Vite logs optimized dependencies changed. reloading. Model preservation flushes on vite:beforeFullReload, so the reloaded page restores the Model captured mid-load and skips init (runtime.ts, restore path). A Query that was Loading at flush time is restored as Loading, its fetch Command is never reissued, and the page stays on the loading state.

Reproduction

rm -rf examples/api-cache-query/node_modules/.vite
cd packages/examples-e2e
EXAMPLE_SLUG=api-cache-query pnpm test:e2e --retries=0

Result: 2 failed, 1 passed (toBeVisible times out waiting for loaded content). Running the same command again on the now-warm cache gives 3 passed. With CI=1 (retries 2) the failures are reported as flaky, so the examples E2E job passes and hides them. The same happens with other Query-backed examples.

Observations

  • A single cold tab opened by hand recovers. Vite still forces the reload (navigation type reload), but the page finishes loading. So far I have only reproduced the hang under Playwright with parallel workers.
  • A consumer app scaffolded with create-foldkit-app (api-cache-query, foldkit from npm) did not force a reload on a cold cache. The late discovery appears specific to the monorepo examples, which alias foldkit/* to source.
  • Possibly related: the plugin keys preserved Models by runtime id only, shares that store across connected clients, and sends foldkit:restore-model with server.ws.send, which broadcasts. Three concurrent cold tabs in one browser did not reproduce the hang, so this is unconfirmed.

Possible directions

  • Do not preserve or restore across a reload caused by dependency optimization. Vite does not distinguish that reload in vite:beforeFullReload, so this would need a signal from the plugin.
  • Have the examples Vite config include these deps in optimizeDeps.include, so a cold start does not trigger a forced reload.

Activity

  1. changed the title [-]Dev: on a cold dep-optimizer cache, Vite's forced reload restores a mid-load Model and the page never finishes loading[/-] [+]Examples E2E: on a cold Vite cache, parallel pages miss the dep-optimizer reload and render blank (hidden by retries)[/+] on Oct 8, 2026
  2. FNDEVVE commented on Oct 8, 2026

    @FNDEVVE
    Author

    Correction after instrumenting the failure: Model preservation is not involved, and the first paragraph above describes the wrong mechanism.

    I ran the api-cache-query E2E pattern (3 parallel Playwright workers, cold node_modules/.vite) with every page's HMR WebSocket frames logged. In the failing run:

    • Vite discovered @effect/platform-browser, clsx, effect/http, effect/persistence, parse5 late and broadcast full-reload.
    • One page had already connected its HMR socket. It received the reload, booted fresh (foldkit:request-model answered with no Model), and loaded.
    • The other two pages connected their sockets just after the broadcast and never received it. Their module requests had already hit 504 (Outdated Optimize Dep), so the entry never executed. Their body stayed empty, and they never sent foldkit:request-model.

    A standalone script that opened the same three pages slightly earlier saw all three receive the reload, and every page loaded. So the hang depends on when each page's HMR socket connects relative to the optimizer's reload, which is why single tabs usually recover and CI retries hide it.

    Apps scaffolded with create-foldkit-app (foldkit from npm) did not trigger a forced reload on a cold cache. The late discovery looks specific to the monorepo examples, which alias foldkit/* to source while the plugin sets optimizeDeps.exclude: ['foldkit']. I have not verified that the exclusion is what stops the scanner from crawling those imports.

    Possible directions: pre-include the discovered deps in the examples' shared Vite config (optimizeDeps.include), or have the E2E harness warm the dev server and wait for optimization before starting workers.

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

    P2Planned: important after P1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions