Skip to content

design(vite-plugin): the ic_env cookie and /api proxy are fixed when vite dev starts, so a canister deployed afterwards never gets its id until the server restarts #664

Description

@b3hr4d

What happens

The plugin runs icp once, in the config hook, and returns the ic_env cookie as a static server.headers["Set-Cookie"] and the /api target as a static server.proxy entry. Nothing re-runs detection while the server lives. So:

  1. A canister deployed after vite dev started never gets its id. Starting the dev server before (or while) deploying is the usual order. The plugin even warns about it, in words that promise the opposite:

    The local replica is running, but no canister ID could be resolved for "backend". Deploy it (icp deploy) — until then the injected ic_env carries no PUBLIC_CANISTER_ID for it and the app will see an undefined canister id.

    After icp deploy, every reload still gets a cookie without PUBLIC_CANISTER_ID:backend, and the reactor throws "canisterId is required ... could not be resolved from the ic_env cookie" until the dev server is restarted.

  2. A network that was down at startup is never picked up. The plugin falls back to proxying /api to http://127.0.0.1:4943 and injects no cookie. icp network start then brings the network up on icp-cli's port (8000 by default), but /api keeps going to 4943 and the page keeps getting no cookie. (The env-only fallback cookie in the same branch already assumes port 8000 for Internet Identity.)

  3. Redeploying into a fresh network state (new canister ids) keeps serving the old ids.

Measured on Vite 4.2.0, 4.5.14, 5.4.21, 6.4.3, 7.3.6 and 8.3.0 with a fake icp whose answers change while the server runs:

vite dev started, backend not deployed:      root key ends ...aaae  PUBLIC_CANISTER_ID:backend=(none)
(icp now reports backend = bkyz2-fmaaa-aaaaa-qaaaq-cai)
after deploy, page reload:                   root key ends ...aaae  PUBLIC_CANISTER_ID:backend=(none)
(network restarted: new root key ...aaaf, backend redeployed as be2us-64aaa-aaaaa-qaaba-cai)
after network restart + redeploy, reload:    root key ends ...aaae  PUBLIC_CANISTER_ID:backend=(none)
icp calls made: 3

#304 listed this as a low-severity note ("ic_env cookie computed once at server start; no re-detection"); it was never filed.

Why it is a design question

Fixing it changes when and how often the plugin runs icp, and how the /api proxy is built:

  • The cookie can be set per response from a configureServer middleware instead of server.headers.
  • The proxy target is fixed in Vite's proxy config. Following a network that moves needs either a plugin-owned proxy or a bypass/configure hook that updates the target.
  • Each icp call takes about 30 ms here (icp 1.5.0), once for the network and once per canister plus internet_identity.

Options

A. Re-detect for document requests, cached. A middleware sets ic_env on HTML responses from a detection result at most a few seconds old, refreshed with async execFile. The cookie follows deploys and network restarts on the next reload. It costs about (2 + N) × 30 ms at most once per cache window, and needs the proxy target to follow the same result.
B. Re-detect only while incomplete. Retry on document requests only while detection failed or a configured canister had no id, and stop once everything resolves. It is cheap and fixes cases 1 and 2. It does not follow a later redeploy (case 3).
C. Keep it static and say so. Change the warning to "deploy it, then restart the dev server", and document that the environment is read once. No behaviour change.

Recommendation

B now, since it fixes the reported workflow (dev server first, deploy second) with almost no cost. Also change the fallback proxy target to follow detection. Consider A only if restarts with fresh network state turn out to be common. Whatever is chosen, the warning text should stop promising something the plugin does not do.

Acceptance (for B)

  • With icp reporting no id for a configured canister at startup, a page load after the canister is deployed receives a cookie carrying its id, without restarting Vite.
  • With the network down at startup, a page load after it comes up receives the cookie, and /api reaches the detected target.
  • Once every configured canister resolved, page loads run no further icp commands.
  • The warning text matches the behaviour.

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