Repository navigation
feat(bolt-vite-react-ts): upgrade to vite 8 - #132
Draft
sheepsteak wants to merge 2 commits into
Draft
sheepsteak wants to merge 2 commits into
sheepsteak wants to merge 2 commits into
Conversation
Bump vite to ^8.3.3 and @vitejs/plugin-react to ^6.1.2 and regenerate the lockfile. Make the build test tolerant of `-` in Vite's base64url hashes and of readdir ordering.
|
|
sheepsteak
marked this pull request as ready for review
October 13, 2026 14:45
geotrev
approved these changes
Oct 13, 2026
sheepsteak
marked this pull request as draft
October 13, 2026 15:30
preview.getByText() and preview.getByRole() from @webcontainer/test return locators scoped to the <iframe> element without entering it, and awaiting them doesn't wait for anything, so the dev test passed without checking the preview. Wait from Playwright's side through page.frameLocator() instead, since the preview is cross-origin and in-page queries can't see into it. With a real assertion the test failed on both Vite 5 and Vite 8: restoring the setup() snapshot drops the executable bit from node_modules/vite/bin/vite.js, so `npm run dev` exits with `spawn vite EACCES`. Install in beforeEach instead of restoring the snapshot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
bolt-vite-react-tsis still on Vite 5 (vite ^5.4.2,@vitejs/plugin-react ^4.3.1), whilebolt-slidesmoved to Vite 8 in #121. The previous attempt (#120) bundled Vite 8 with React 19, Tailwind 4, TypeScript 6, and removing ESLint, and was reverted in #123.Solution
Upgrade only the build tooling:
viteto^8.3.3and@vitejs/plugin-reactto^6.1.2(the v6 line targets Vite 8). React 18, Tailwind 3 with PostCSS, ESLint, TypeScript, andvite.config.tsare unchanged. The existingresolve.aliasandoptimizeDeps.excludeoptions still work in Vite 8.Implementation Details
npm cipasses with it. Only the Vite toolchain moved: Babel, esbuild, and Rollup drop out, Rolldown and Lightning CSS come in, andpostcssgoes from 8.4 to 8.5 because Vite 8 requires^8.5.28.removeFileHash: reapplies the fix from feat(bolt-vite-react-ts): modernize toolchain and remove eslint #120. Vite hashes are base64url and can contain-, so the regex now strips from the first-up to the file extension.readdirin the WebContainer returnedindex.jsbeforeindex.css. Older Vite 5 checkouts of the template fail the same way, so the ordering isn't specific to Vite 8.preview.getByText()andpreview.getByRole()from@webcontainer/testreturn locators scoped to the<iframe>element without entering it, and awaiting them doesn't wait; a probe resolved in 0ms with no dev server running. The preview is cross-origin, so in-page queries such asexpect.element()can't see into it either. The test now waits from Playwright's side throughpage.frameLocator(), using a smallwaitForVisiblebrowser command invitest.config.ts.setup()snapshot: with a real assertion the dev test failed on both Vite 5 and Vite 8. Restoring thesetup()snapshot drops the executable bit fromnode_modules/vite/bin/vite.js(-rwxrwxr-xafternpm install,-rw-r--r--after restore), sonpm run devexited withspawn vite EACCES. The test now mounts and installs inbeforeEachinstead. The other test files (angular,astro-shadcn,bolt-expo,nextjs,slidev,sveltekit) use the samesetup()andpreview.getBy*pattern, so their dev tests aren't checking the preview either. That's left for a follow-up..bolt/prompt: unchanged. The Vite 8 note feat(bolt-vite-react-ts): modernize toolchain and remove eslint #120 added was aboutresolve.tsconfigPaths, which this PR doesn't adopt.bolt-*templates:bolt-slidesis already on Vite 8, andbolt-expo(Metro) andbolt-remotion(Webpack) don't use Vite.bolt-qwikstays on Vite 5: Qwik 1.x, including the latest 1.20.2, declaresvite: ">=5 <8", sonpm installfails with ERESOLVE, and even with overrides the client build fails under Rolldown. Vite 8 needs the Qwik 2 migration (@qwik.dev/core, currently 2.0.0-rc.2), which can wait until Qwik 2 is stable.Performance in WebContainer
Vite 8 is slower than Vite 5 on a cold dev server start in WebContainer: the first styled preview takes about 6.5s longer. HMR and production builds are about the same.
@rolldown/binding-wasm32-wasinpm installnpm run devto styled first rendernpm run build(wall clock)Method:
@webcontainer/testwith Vitest browser mode in headless Chromium on an Apple Silicon Mac. Each run launches a fresh Chromium and boots a fresh WebContainer. The first two columns have 5 runs each. The third column comes from a separate batch of 4 runs, interleaved with 4 Vite 8 control runs that matched the first batch within 6%. "Styled first render" is a Playwright wait inside the preview iframe until the starter text is present and Tailwind'sbg-gray-100is the computed background. Running 4 rounds in one browser session gives the same pattern, so the cost comes back with every WebContainer boot, not just in a cold browser.Cause. In WebContainer, npm installs Rolldown's native
@rolldown/binding-linux-x64-gnu, which can't load there. Rolldown 1.2.13 no longer lists@rolldown/binding-wasm32-wasiin itsoptionalDependencies. So its binding loader falls back to a WebContainer-specific branch that runspnpm i @rolldown/binding-wasm32-wasi@1.2.13into/tmp/rolldown-1.2.13the first time Rolldown is imported. That's 7 packages, including an 11.4 MB WASM binding. In a fresh WebContainer the firstimport('rolldown')took 6.2s (pnpm reported "Done in 5.2s"), and the next two took 356ms and 335ms./tmpdoesn't carry over to a new WebContainer, so every new project pays the download.Possible mitigation (not in this PR). Rolldown's loader checks
node_modules/@rolldown/binding-wasm32-wasibefore it falls back to the download. So adding"@rolldown/binding-wasm32-wasi": "1.2.13"to devDependencies gives the third column: cold start drops from 8.9s to 3.3s, install takes about 0.2s longer, and the download ran in 0 of 4 runs (4 of 4 without it). The costs:vite@8.3.3depends onrolldown ~1.2.11), and the loader doesn't check the version unlessNAPI_RS_ENFORCE_VERSION_CHECKis set.node_moduleson every machine, unused outside WebContainer.Providing or caching the Rolldown WASM binding in WebContainer itself would fix every Vite 8 project without pins. Even with either fix, Vite 8 stays about 0.9s slower on cold start and about 2x slower on dev server restart than Vite 5. That remaining cost comes from running Rolldown and Oxc as WASM.
Test plan
npm ci,npm run build,npm run typecheck,tsc --noEmit -p tsconfig.node.json, andnpm run lintpass inbolt-vite-react-ts@/importstest/bolt-vite-react-ts.test.tspasses in Chromium: build in a WebContainer, and the dev server preview renders and updates on edit, asserted inside the iframe