diff --git a/apps/web/package.json b/apps/web/package.json index e7e1177e..a9cb215d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -46,7 +46,7 @@ "@tailwindcss/vite": "^4.1.0", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^5.0.0", + "@vitejs/plugin-react": "^5.2.0", "@vitest/browser": "^4.1.11", "@vitest/browser-playwright": "^4.1.11", "@vitest/coverage-istanbul": "^4.1.11", @@ -54,7 +54,7 @@ "storybook": "^10.5.5", "tailwindcss": "^4.1.0", "typescript": "^6.0.3", - "vite": "^7.0.0", + "vite": "^8.2.2", "vitest": "^4.1.11", "vitest-browser-react": "^1.0.0" } diff --git a/bun.lock b/bun.lock index aa8ca1b3..005c7c66 100644 --- a/bun.lock +++ b/bun.lock @@ -83,7 +83,7 @@ "@tailwindcss/vite": "^4.1.0", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^5.0.0", + "@vitejs/plugin-react": "^5.2.0", "@vitest/browser": "^4.1.11", "@vitest/browser-playwright": "^4.1.11", "@vitest/coverage-istanbul": "^4.1.11", @@ -91,7 +91,7 @@ "storybook": "^10.5.5", "tailwindcss": "^4.1.0", "typescript": "^6.0.3", - "vite": "^7.0.0", + "vite": "^8.2.2", "vitest": "^4.1.11", "vitest-browser-react": "^1.0.0", }, @@ -2204,7 +2204,7 @@ "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], - "vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="], + "vite": ["vite@8.2.2", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.26", "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q=="], "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], @@ -2302,8 +2302,6 @@ "astro/magic-string": ["magic-string@1.2.3", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g=="], - "astro/vite": ["vite@8.2.2", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.26", "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q=="], - "body-parser/content-type": ["content-type@2.1.0", "", {}, "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag=="], "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], @@ -2352,8 +2350,6 @@ "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "vitest/vite": ["vite@8.2.2", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.26", "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q=="], - "@astrojs/markdown-satteri/satteri/@bruits/satteri-darwin-arm64": ["@bruits/satteri-darwin-arm64@0.10.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA=="], "@astrojs/markdown-satteri/satteri/@bruits/satteri-darwin-x64": ["@bruits/satteri-darwin-x64@0.10.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q=="], @@ -2404,8 +2400,6 @@ "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "astro/vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], "eslint-plugin-jsx-a11y/minimatch/brace-expansion": ["brace-expansion@1.1.18", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw=="], @@ -2474,8 +2468,6 @@ "unstorage/chokidar/readdirp": ["readdirp@5.1.1", "", {}, "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA=="], - "vitest/vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "eslint-plugin-jsx-a11y/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "storybook/@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], diff --git a/docs/migrations/2026-08-31-vite.md b/docs/migrations/2026-08-31-vite.md index f4eb9e7c..14a514cf 100644 --- a/docs/migrations/2026-08-31-vite.md +++ b/docs/migrations/2026-08-31-vite.md @@ -268,3 +268,135 @@ Not listed among BC-A1's call sites. `@vitest/browser@4` dropped its `./provider - `.gitignore`: Vitest 4 writes failure screenshots to a new `**/.vitest-attachments/` directory (alongside the already-ignored `**/__screenshots__/`). Ignored, so test runs don't leave untracked binaries. - BC-A2's 36-file `@vitest/browser/context` → `vitest/browser` sweep was included. It required an `eslint --fix` pass afterwards: the new specifier sorts differently under `simple-import-sort`, tripping the lint gate in all 36 files. - BC-A3 and BC-A4 were confirmed correct — no `invocationCallOrder` or automock fixes were needed. + +--- + +## POST-IMPLEMENTATION CORRECTIONS — PR B, as actually landed (2026-08-31) + +Landing PR B surfaced five more errors in the plan body, one of them a material understatement of the +migration's own scope. **Read this alongside the PR A corrections above.** + +### CORRECTION 6 (understated scope): Vite 8 is a FOUR-engine swap, not just the dep optimizer + +BC-B1 describes Vite 8 as replacing "esbuild with Rolldown for dependency pre-bundling/scanning" and +calls the `optimizeDeps` scanner "THE highest-risk item in this whole migration". That is one of four +engine swaps, and not the one that touches the shipped artifact. Vite 8 actually replaces: + +| Concern | Vite 7 | Vite 8 | +|---|---|---| +| Production bundler | **Rollup** | **Rolldown** | +| JS transform | esbuild | Oxc | +| JS minifier | esbuild | Oxc Minifier | +| CSS minifier | esbuild | **Lightning CSS** | +| Dep pre-bundling | esbuild | Rolldown *(the only one PR A already exercised)* | + +Confirmed by the installed package's own dependency set: `vite@7.3.6` depends on `esbuild` + `rollup`; +`vite@8.2.2` depends on `rolldown` + `lightningcss`, and demotes `esbuild` to an **optional peer**. + +Renamed/removed config surfaces that come with it: `build.rollupOptions` → `build.rolldownOptions`, +`worker.rollupOptions` → `worker.rolldownOptions`, the `esbuild:` config option → `oxc:` (with +`esbuild.jsx: 'automatic'` becoming `oxc.jsx: { runtime: 'automatic' }`), removal of the `manualChunks` +object form, removal of `build.rollupOptions.watch.chokidar`, and dropped `system`/`amd` output formats. + +**Why PR B still needed zero config edits:** this repo configures *none* of them. Grepped the whole tree — +no `rollupOptions`, no `manualChunks`, no `esbuild:`/`esbuildOptions`, no `worker:`, no `import.meta.hot`, +no lib/formats build. The correct justification for "no config-shape edits required" is *"the repo uses +none of the renamed options"*, **not** BC-B1's *"the API is unchanged"* — the API did change, this repo +just never touched the parts that moved. + +### CORRECTION 7: PR A did NOT pre-pay the Rolldown risk for the build path + +CORRECTION 1 concludes "the Rolldown risk is already paid and measured". That is true **only for the +dep-optimizer in the test path**. PR A left `node_modules/vite` at 7.3.6, so the production build kept +running Rollup + esbuild-minify + esbuild-CSS-minify the entire time. Rollup→Rolldown bundling, Oxc +minification and Lightning CSS all land for the first time **here, in PR B**. The app build and dev +server were genuinely the new risk surface; the test runner was not. + +### CORRECTION 8: `@vitejs/plugin-react` was ALREADY on 5.2.0 before this PR + +BC-B3 presents `5.0.0 → 5.2.0` as a version move. The manifest range was `^5.0.0`, which had already +semver-resolved to `5.2.0` on the parent branch (verified on disk pre-change). The `package.json` edit is +a **floor tightening only** — it documents the vite-8-capable minimum and changes nothing about what is +installed. The lockfile shows no resolved-version change for this package. + +### CORRECTION 9 (the plan predicted the opposite): vite 8 DE-DUPLICATES the tree + +CORRECTION 1 documents the three-copy split PR A created (root 7.3.6 + `vitest/vite` 8.2.2 + +`astro/vite` 8.2.2). Bumping the app to 8.2.2 collapses all three into the single hoisted root copy. +The lockfile delta for this entire PR is **four entries removed, zero added**: + +``` +- "astro/vite" - "astro/vite/fsevents" +- "vitest/vite" - "vitest/vite/fsevents" +``` + +There is now exactly **one** `vite` in the tree. Installed package count drops accordingly (884 with a +clean `--frozen-lockfile` install; all 11 `@nightcore/*` workspace links present, hoisted linker intact, +`e2e:ring3 --prove` green). So PR B is net-simplifying, not additive — and the "vitest carries its own +vite 8 either way" caveat in CORRECTION 1 stops being true the moment PR B lands. + +### CORRECTION 10: PR A's `esbuildOptions` deprecation warning is RESOLVED by PR B + +The warning CORRECTION 1 quotes (`vite:react-babel` setting the deprecated `optimizeDeps.esbuildOptions`) +came from plugin-react targeting a vite-7 API while vitest ran vite 8. With the app on vite 8 too, +plugin-react 5.2.0 emits the `rolldownOptions` form instead. **Zero occurrences** across both cold-cache +`test:web` runs and the production build. PR B cleans up a warning PR A introduced. + +### CORRECTION 11: rollback + +CORRECTION 1 already voided the plan's original rollback claim. Completing it: reverting PR B does not +reach a clean state either — it restores the **three-copy** vite tree (root 7.3.6 + two nested 8.2.2) +and re-introduces the `esbuildOptions` deprecation warning. Reverting PR A and PR B together is the only +route back to a single-vite-7 tree. + +### Measured results (PR B) + +**Storybook × vite 8 — admitted, not a blocker.** Every vite-peer consumer in the tree accepts `^8.0.0`: +`@storybook/react-vite@10.5.10` and `@storybook/builder-vite@10.5.10` both declare +`^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0`; also `@tailwindcss/vite@4.3.3` (`^5.2.0 || ^6 || ^7 || ^8`), +`@vitejs/plugin-react@5.2.0`, `@joshwooding/vite-plugin-react-docgen-typescript@0.7.0`, `@vitest/mocker`, +`vitefu`, and `vitest@4.1.11`. `astro@7.2.9` requires `^8.0.13` — satisfied by the now-shared 8.2.2. + +**`optimizeDeps` guards needed NO adjustment.** All three locations +(`vite.config.ts` has none; `vitest.config.ts` both projects; `.storybook/main.ts`) were left byte-identical. +The include lists tuned against esbuild's scanner remain sufficient under Rolldown's — now confirmed for +the build path as well as the test path. + +**F3 cold-cache trap did not reproduce.** `bun run test:web` ×2, each preceded by +`rm -rf apps/web/node_modules/.vite`: 517 files / 2953 tests passed both times, **zero** occurrences of +`optimized dependencies changed`. `test:stories` (207 files / 918 tests) likewise clean. + +**Production build is green and materially faster.** `vite build` 3.81s → **715ms** (~5.3×). + +| | vite 7.3.6 | vite 8.2.2 | Δ | +|---|---|---|---| +| dist files | 43 | 53 | +10 (finer code-splitting) | +| dist total | 3,163,690 B | 3,187,272 B | **+0.75%** | +| main JS chunk | 751.94 kB (gzip 229.63) | 691.43 kB (gzip 205.81) | **−60.5 kB / −23.8 kB gzip** | +| main CSS | 109,089 B | 115,465 B | +5.8% (Lightning CSS syntax lowering, documented) | +| CSS files / SVG / html | 2 / 1 / 1 | 2 / 1 / 1 | unchanged | + +Output integrity verified, not assumed: all 21 assets referenced by `index.html` plus **301** inter-chunk +relative references resolve on disk; **zero** absolute `/assets` paths, so `base: './'` still satisfies +Tauri's custom-protocol requirement; `@layer`, `prefers-reduced-motion` and the `--nc-*` custom properties +all survive Lightning CSS minification. Chunk filenames became semantic (`terminal-*`, `settings-*`, +`council-*`, `prreview-*`) where Rollup emitted repeated `index-*`, and Vite 8 additionally emits +`` hints Vite 7 did not. + +**Two new advisory warnings** appear from Rolldown, both pre-existing code conditions rather than +regressions — `[INEFFECTIVE_DYNAMIC_IMPORT]` for `@tauri-apps/plugin-dialog` and `src/components/board/index.ts`, +each dynamically imported somewhere but also statically imported elsewhere, so the dynamic import cannot +split them into their own chunk. Harmless today; a cheap code-splitting win if anyone wants it. The +chunk-size advisory also now points at `build.rolldownOptions.output.codeSplitting` instead of +`manualChunks`. + +**CJS interop (the "Consistent CommonJS Interop" break) is a non-issue here.** Only two default-import +sites exist in `apps/web/src`: `dompurify` and `shiki/**/*.mjs`. `dompurify` ships a `module`/`exports` +ESM build so Vite resolves ESM and the CJS rule never applies; the shiki imports are literal `.mjs`. +No default import of `react`/`react-dom` exists anywhere (only `import type`). + +**Dev-server path smoke-tested non-interactively.** `vite --port 5173 --strictPort` (the exact +`beforeDevCommand` Tauri's `devUrl` polls) reports `VITE v8.2.2 ready in 163 ms`, serves `/` at 200 with +plugin-react's Babel Fast-Refresh preamble injected, transforms `/src/main.tsx` at 200, and serves +`/@vite/client` at 200. **Still owed: a GUI `bun run desktop` run** to confirm the Tauri WebView window +itself renders — that needs an interactive session and was not attempted.