From d94df427a1547e9bbe54485f0ee4b423976b890d Mon Sep 17 00:00:00 2001 From: Julien Gautier Date: Fri, 15 May 2026 20:03:29 +0200 Subject: [PATCH] fix(docs): pre-bundle mermaid deps so the dev server resolves dayjs/cytoscape (#157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary `pnpm docs:dev` rendered a blank page with this thrown by the browser on the first navigation: ``` Uncaught SyntaxError: The requested module '/@fs/.../node_modules/.pnpm/dayjs@1.11.20/node_modules/dayjs/dayjs.min.js?v=…' does not provide an export named 'default' (at chunk-AGHRB4JF.mjs?v=…:9:8) ``` Root cause: Mermaid 11 (transitive dep of `vitepress-plugin-mermaid` shipped in #154) pulls in `dayjs`, `cytoscape`, `debug`, `@braintree/sanitize-url` — each ships a CommonJS `main` field with no `default` ESM export. Vite's dev server resolves these modules eagerly as ESM and the browser blows up before the home page renders. The **production build was unaffected** — Rollup's plugin pipeline already wraps CJS deps for ESM consumers. `docs:build` shipped clean HTML in #154 and the CI Mermaid-fence (`grep class="mermaid"` in ADR-0009's HTML) passed precisely because it inspects the prod bundle, not the dev-server output. ## What lands [`docs/.vitepress/config.mts`](docs/.vitepress/config.mts) — adds a single `vite.optimizeDeps.include` block: ```ts vite: { optimizeDeps: { include: ['mermaid', 'dayjs', 'debug', '@braintree/sanitize-url'], }, }, ``` `optimizeDeps.include` tells Vite to pre-bundle those modules through esbuild at dev-server boot, applying the same CJS→ESM interop wrapper Rollup uses in prod. The dev server now serves a working `localhost:5173` and Mermaid diagrams render. ## Notes for the reviewer - **Why these four names specifically?** They are the Mermaid deps that ship CJS-only entrypoints. Adding `'mermaid'` alone is sometimes enough because Vite walks the dep tree, but the plugin's own README + a handful of upstream issue threads recommend listing the leaf CJS modules explicitly so the optimizer doesn't miss them on a cold cache. Cheap, defensive. - **Why didn't the CI gate catch this?** The `Assert Mermaid renders` step in `.gitea/workflows/docs-site.yml` greps `docs/.vitepress/dist/` — the production-build output. The bug only manifests on the dev server's runtime-pre-bundling path. Catching it in CI would require booting `docs:dev` headlessly and curling the page; not worth the workflow weight for a once-per-major-upgrade class of issue. Manual `pnpm docs:dev` smoke is the right gate for now. - **Why not bump dayjs / mermaid?** Dayjs's package shape is a long-standing upstream quirk (the `main` points at the UMD/CJS bundle); fixing it upstream would be a breaking change for non-bundler consumers. Mermaid upstream is aware; their fix has historically been "tell your bundler to pre-bundle us", which is exactly what `optimizeDeps.include` does. ## Test plan - [x] `rm -rf docs/.vitepress/cache && pnpm docs:dev` — server boots, `curl http://localhost:5173/` returns 200. - [x] `rm -rf docs/.vitepress/{cache,dist} && pnpm docs:build` — clean prod build in ~10 s, Mermaid SVG still present in ADR-0009's HTML (regression fence passes). - [ ] Manual smoke: with the fix applied, navigate `localhost:5173` → home → `/decisions/0009-…` → confirm the OIDC sequence diagram renders inline, no console errors. Toggle dark mode, confirm diagrams flip theme. --------- Co-authored-by: Julien Gautier Reviewed-on: https://git.unespace.com/julien/apf_portal/pulls/157 --- docs/.vitepress/config.mts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 7d315ea..acb7268 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -160,5 +160,20 @@ export default withMermaid( mermaid: { securityLevel: 'strict', }, + + // Mermaid 11 ships its `dayjs` / `cytoscape` dependencies with a + // CommonJS `main` field but no `default` ESM export. Vite's dev + // server resolves those modules eagerly as ESM and the browser + // throws `does not provide an export named 'default'` on the + // first navigation. Telling `optimizeDeps` to pre-bundle the + // Mermaid dependency tree forces the CJS→ESM interop wrapper + // that Vite's Rollup-based build already applies in prod. The + // production build (`docs:build`) was unaffected even before + // this; this fix is exclusively for the `docs:dev` happy path. + vite: { + optimizeDeps: { + include: ['mermaid', 'dayjs', 'debug', '@braintree/sanitize-url'], + }, + }, }), );