fix(deps): scope the vite < 7 override to vitepress so @angular/build keeps vite 8 #163

Merged
julien merged 1 commits from fix/scope-vite-override-to-vitepress into main 2026-05-16 02:07:44 +02:00
Owner

Summary

Hotfix on the override added in #161. The unconditional "vite": ">=6.4.2 <7" was too broad — it downgraded every vite consumer in the workspace to vite 6.4.2, including @angular/build@21.2.11. Angular's dev-server plugin (angular-memory-plugin.js > loadViteClientCode) monkey-patches Vite's client error-overlay code; the patch targets vite 8.x's internal layout, fails against vite 6, and the home page blank-screens with:

[vite] Internal server error: Failed to update Vite client error overlay text.
  at loadViteClientCode (angular-memory-plugin.js:140:31)

…on the very first request to pnpm nx serve portal-shell.

Fix

One-line change in package.jsonpnpm.overrides:

- "vite":          ">=6.4.2 <7",
+ "vitepress>vite": ">=6.4.2 <7",

pnpm's parent>child selector syntax scopes the override to vitepress's transitive resolution only. Other vite consumers (Angular, Nx, Vitest, the analog plugin) follow their own peer constraints and resolve to vite 8.0.13 again.

Resolution after the fix

Consumer vite version Why
vitepress 1.6.4 6.4.2 Override target — keeps VitePress 1.x off rolldown-vite
@angular/build 21.2.11 8.0.13 Restored; its dev-server plugin needs vite 8's client layout
@nx/vite, @analogjs/vite-plugin-angular, Vitest 8.0.13 Restored
@vitejs/plugin-basic-ssl (analog transitive) 7.3.2 Its own peer range; HTTPS-cert helper only, not the dev-server host. Doesn't affect us.

Why this regression didn't surface in #161's CI

The docs-site.yml workflow and pnpm exec nx run-many -t lint test build exercise the production build paths. Vite 6 ↔ Angular-build 21.2's monkey-patch incompatibility is a dev-server-only failure (the prod Rollup pipeline doesn't go through loadViteClientCode). CI couldn't have caught it; manual nx serve portal-shell is the only repro path. Lesson logged.

Test plan

  • pnpm install — clean. Lockfile diff confirms: vite 6.4.2 only under vitepress, vite 8.0.13 restored everywhere else.
  • pnpm audit --audit-level=moderate — no known vulnerabilities.
  • pnpm docs:build — ~9.5 s, Mermaid still renders in ADR-0009's HTML (regression fence passes).
  • pnpm exec nx run-many -t lint test build --projects=portal-shell,portal-admin,portal-bff,shared-ui,shared-state,feature-auth — green.
  • pnpm nx serve portal-shell — boots cleanly, curl http://localhost:4200/ returns HTTP 200 with the SPA shell, no loadViteClientCode error in the dev log. (This is the path that broke.)
  • Manual smoke (the user's repro)pnpm nx serve portal-shell, open the home page in a browser, confirm:
    • No "Failed to update Vite client error overlay text" in the browser DevTools console.
    • Page renders; navigating to /accessibility, /profile works.
    • Theme switcher in the footer toggles light / dark / system; locale switcher likewise.

Notes for the reviewer

  • Lesson on override scoping: the version-selector form ("package@<vuln-range>": "patched") is the safest default — it only kicks in for the vulnerable range. The unconditional form ("package": "<range>") is a sledgehammer and should be reserved for cases where the version-selector form genuinely can't express the intent (as was the case in #161 where the resolved version was already past the vulnerable range, so the selector was a no-op). When the unconditional form is needed, always scope to a parent ("parent>package": …) to avoid the workspace-wide blast radius.
  • No documentation change in this PR: development.md's "Transitive vulnerabilities — pnpm.overrides" subsection (from #160) is still accurate. A follow-up edit could add a "scope to a parent when possible" sentence; not blocking.
## Summary Hotfix on the override added in [#161](https://git.unespace.com/julien/apf_portal/pulls/161). The unconditional `"vite": ">=6.4.2 <7"` was too broad — it downgraded **every** vite consumer in the workspace to vite 6.4.2, including `@angular/build@21.2.11`. Angular's dev-server plugin (`angular-memory-plugin.js > loadViteClientCode`) monkey-patches Vite's client error-overlay code; the patch targets vite 8.x's internal layout, fails against vite 6, and the home page blank-screens with: ``` [vite] Internal server error: Failed to update Vite client error overlay text. at loadViteClientCode (angular-memory-plugin.js:140:31) ``` …on the very first request to `pnpm nx serve portal-shell`. ## Fix One-line change in [`package.json`](package.json) → `pnpm.overrides`: ```diff - "vite": ">=6.4.2 <7", + "vitepress>vite": ">=6.4.2 <7", ``` pnpm's `parent>child` selector syntax scopes the override to vitepress's transitive resolution only. Other vite consumers (Angular, Nx, Vitest, the analog plugin) follow their own peer constraints and resolve to vite 8.0.13 again. ## Resolution after the fix | Consumer | vite version | Why | | --- | --- | --- | | `vitepress 1.6.4` | **6.4.2** | Override target — keeps VitePress 1.x off rolldown-vite | | `@angular/build 21.2.11` | **8.0.13** | Restored; its dev-server plugin needs vite 8's client layout | | `@nx/vite`, `@analogjs/vite-plugin-angular`, Vitest | **8.0.13** | Restored | | `@vitejs/plugin-basic-ssl` (analog transitive) | 7.3.2 | Its own peer range; HTTPS-cert helper only, not the dev-server host. Doesn't affect us. | ## Why this regression didn't surface in #161's CI The `docs-site.yml` workflow and `pnpm exec nx run-many -t lint test build` exercise the **production build** paths. Vite 6 ↔ Angular-build 21.2's monkey-patch incompatibility is a **dev-server-only** failure (the prod Rollup pipeline doesn't go through `loadViteClientCode`). CI couldn't have caught it; manual `nx serve portal-shell` is the only repro path. Lesson logged. ## Test plan - [x] `pnpm install` — clean. Lockfile diff confirms: vite 6.4.2 only under vitepress, vite 8.0.13 restored everywhere else. - [x] `pnpm audit --audit-level=moderate` — no known vulnerabilities. - [x] `pnpm docs:build` — ~9.5 s, Mermaid still renders in ADR-0009's HTML (regression fence passes). - [x] `pnpm exec nx run-many -t lint test build --projects=portal-shell,portal-admin,portal-bff,shared-ui,shared-state,feature-auth` — green. - [x] **`pnpm nx serve portal-shell`** — boots cleanly, `curl http://localhost:4200/` returns HTTP 200 with the SPA shell, no `loadViteClientCode` error in the dev log. (This is the path that broke.) - [ ] **Manual smoke (the user's repro)** — `pnpm nx serve portal-shell`, open the home page in a browser, confirm: - No "Failed to update Vite client error overlay text" in the browser DevTools console. - Page renders; navigating to `/accessibility`, `/profile` works. - Theme switcher in the footer toggles light / dark / system; locale switcher likewise. ## Notes for the reviewer - **Lesson on override scoping**: the version-selector form (`"package@<vuln-range>": "patched"`) is the safest default — it only kicks in for the vulnerable range. The unconditional form (`"package": "<range>"`) is a sledgehammer and should be reserved for cases where the version-selector form genuinely can't express the intent (as was the case in #161 where the resolved version was already past the vulnerable range, so the selector was a no-op). When the unconditional form is needed, **always scope to a parent** (`"parent>package": …`) to avoid the workspace-wide blast radius. - **No documentation change in this PR**: development.md's "Transitive vulnerabilities — `pnpm.overrides`" subsection (from #160) is still accurate. A follow-up edit could add a "scope to a parent when possible" sentence; not blocking.
julien added 1 commit 2026-05-16 02:05:38 +02:00
fix(deps): scope the vite < 7 override to vitepress so @angular/build keeps vite 8
CI / commits (pull_request) Successful in 3m8s
CI / scan (pull_request) Successful in 3m22s
CI / check (pull_request) Successful in 5m27s
CI / a11y (pull_request) Successful in 2m4s
Docs site / build (pull_request) Successful in 2m40s
CI / perf (pull_request) Successful in 6m21s
de30299464
The unconditional `"vite": ">=6.4.2 <7"` override added in #161 to
keep VitePress 1.x off rolldown-vite (vite 7+) had the side effect
of downgrading **every** vite consumer in the workspace to vite
6.4.2 — including `@angular/build@21.2.11`, whose internal
`angular-memory-plugin.js > loadViteClientCode` monkey-patches the
Vite client error-overlay code. The patch targets vite 8.x's
internal layout; against vite 6 it throws:

  [vite] Internal server error: Failed to update Vite client error
  overlay text.
    at loadViteClientCode (angular-memory-plugin.js:140:31)

…on the very first request to `pnpm nx serve portal-shell`. The
shell renders a blank screen until the workspace's vite is back to
8.x.

Fix: scope the override to vitepress's transitive resolution only,
using pnpm's `parent>child` selector syntax. Diff is one line:

-  "vite":          ">=6.4.2 <7",
+  "vitepress>vite": ">=6.4.2 <7",

Post-fix resolutions (verified against pnpm-lock):
  - VitePress → vite@6.4.2 (Rollup-based, VitePress 1.x compatible)
  - @angular/build, @nx/vite, Vitest, etc. → vite@8.0.13 (restored)
  - @vitejs/plugin-basic-ssl (analog dep) → vite@7.3.2 (its own
    peer range; not the patched-7+ rolldown branch in a way that
    affects us — it's used for HTTPS-cert generation only, not
    dev-server hosting).

Verification:
  * `pnpm audit --audit-level=moderate` → no known vulnerabilities.
  * `pnpm docs:build` → 9.5 s, Mermaid still renders in ADR-0009.
  * `pnpm nx run-many -t lint test build` on the 6 main projects
    → all green.
  * `pnpm nx serve portal-shell` → boots cleanly, HTTP 200 on
    `/`, no `loadViteClientCode` error in the dev log.
julien merged commit bba1703622 into main 2026-05-16 02:07:44 +02:00
julien deleted branch fix/scope-vite-override-to-vitepress 2026-05-16 02:07:46 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#163