Early look at Astro 7 alpha with Vite 8 and Rolldown
Updating this blog to Astro 7 alpha surfaced vite version conflicts, rolldown type incompatibilities, and the fact that pnpm update bypasses minimumReleaseAge.
Astro 7 alpha ships with Vite 8 and rolldown: the Rust-based bundler that replaces rollup. I migrated this blog to test the new stack and hit several issues worth documenting.
Upgrade baseline
Astro 6 uses Vite 7, which bundles rollup as its production bundler. Vite 8 replaces rollup with rolldown, a Rust-based bundler that’s 10-30x faster in benchmarks. The plugin API is compatible, but the type systems are different. Rolldown’s PluginContextMeta has a rolldownVersion property that rollup’s doesn’t.
The @tailwindcss/vite plugin declares vite: "^5.2.0 || ^6 || ^7 || ^8" as a peer dependency. When pnpm resolved it to vite 8 while astro stayed on vite 7, two different bundlers coexisted in node_modules. The type error:
Type 'Plugin<any>[]' is not assignable to type 'PluginOption'.
Types of property 'meta' are incompatible.
Property 'rolldownVersion' is missing in type 'MinimalPluginContext'
but required in type 'MinimalPluginContext'.
This is a known issue: Astro issue #16542 documents the exact same error.
Migration notes
How vite@8 got into the tree
Running pnpm update --latest bumped vitest and other dev dependencies. Some of these pulled in vite@8 as a peer dependency. pnpm resolved @tailwindcss/vite to vite 8 (which it accepts), while astro and @astrojs/vue stayed on vite 7. The lockfile ended up with two vite versions:
pnpm ls vite --depth 1
dependencies:
├─┬ @astrojs/vue@6.0.1
│ └── vite@7.3.5
├─┬ astro@6.4.4
│ └── vite@7.3.5
devDependencies:
├─┬ @tailwindcss/vite@4.3.0
│ └── vite@8.0.16 peer
└─┬ vitest@4.1.8
└── vite@8.0.16 peer
Postcss detour
Before settling on Astro 7 alpha, I tried switching from @tailwindcss/vite to @tailwindcss/postcss as a local workaround (never committed). The approach:
- Removed
@tailwindcss/vitefrom devDependencies - Added
@tailwindcss/postcssandpostcss - Created
postcss.config.ts - Removed the
tailwindcss()vite plugin fromastro.config.ts
The build worked, but the setup was more complex: an extra config file, an extra dependency, and a departure from both the Astro docs and Tailwind docs, which deprecated the @astrojs/tailwind PostCSS integration in favor of @tailwindcss/vite. I discarded these changes once the Astro 7 alpha route became available.
The real fix: Astro 7 alpha
Astro 7.0.0-alpha.2 depends on vite: "^8.0.13". With astro on vite 8, all packages resolve to a single vite version:
pnpm ls vite --depth 1
dependencies:
├─┬ @astrojs/vue@7.0.0-alpha.0
│ └── vite@8.0.16
├─┬ astro@7.0.0-alpha.2
│ └── vite@8.0.16
devDependencies:
├─┬ @tailwindcss/vite@4.3.0
│ └── vite@8.0.16 peer
└─┬ vitest@4.1.8
└── vite@8.0.16 peer
I discarded the postcss changes, re-added @tailwindcss/vite@4.3.0, and deleted postcss.config.ts. The vite plugin works natively with vite 8: no conflict.
TypeScript 6
Upgraded from 5.9.3 to 6.0.3. The main breaking change: the default types value changed from auto-including everything in node_modules/@types to [] (empty). Projects that relied on implicit Node.js types suddenly lose process, Buffer, and other globals.
The fix: adding to tsconfig.json:
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"types": ["node"]
}
}
The TypeScript 6 migration guide recommends this for most projects. A ts5to6 codemod handles it automatically.
Removing shamefullyHoist
shamefullyHoist: true hoists packages to the root node_modules, which can cause pnpm to resolve peer dependencies to unexpected versions. I removed it to enforce stricter dependency isolation; each package gets only what it declares.
minimumReleaseAgeExclude for alphas
The alpha packages (astro@7.0.0-alpha.2, @astrojs/vue@7.0.0-alpha.0) were published hours before I tried to install them. pnpm’s minimumReleaseAge: 1440 blocked the install. I added temporary exclusions:
minimumReleaseAgeExclude:
- astro@7.0.0-alpha.2
- "@astrojs/vue@7.0.0-alpha.0"
These should be removed once the alphas pass the 1-day cooldown window. The third post in the supply chain series covers why exclusion lists need periodic review.
Verification
| Astro 6.4 + vite 7.3.2 + rollup | Astro 7 alpha + vite 8.0.16 + rolldown | |
|---|---|---|
| Warmup | 6.09s | 0.95s |
| Run 1 | 1.11s | 0.63s |
| Run 2 | 1.10s | 0.64s |
| Run 3 | 1.11s | 0.62s |
| Run 4 | 1.10s | 0.63s |
| Run 5 | 1.12s | 0.63s |
| Median | 1.11s | 0.63s |
| Pages | 65 | 72 |
Methodology
Same blog content (verified with git diff ba6cfdc..HEAD -- src/content/blog/; zero changes), same lockfile, same machine. The page count difference (65 vs 72) comes from build-level changes between versions; the vite8 tree has a newer BaseLayout.astro, apple-touch-icon.png, and site.webmanifest.
Both builds ran on a Mac16,10 (Apple M4, 16 GB):
rm -rf dist .astrothenpnpm build(warm-up, caches image generation and types)- Five timed runs:
rm -rf dist .astrobetween each, thenpnpm build - Median reported
Revisit after stable
pnpm update --latest bypassed the Renovate cooldown flow, pulling in vite@8 before astro supported it. The version conflict surfaced as a rolldown/rollup type mismatch; upgrading to Astro 7 alpha was the fix.
References
- Astro issue #16542.
@tailwindcss/viteincompatibility with Astro 6 + vite 8 - Vite 8.0 announcement. Rolldown integration and migration guide
- Astro styling guide. Tailwind 4 setup and
@astrojs/tailwinddeprecation - Tailwind Astro framework guide. Official vite plugin setup
- TypeScript 6.0 release notes. Breaking changes and migration
- Astro 7 alpha announcement. Vite 8 support preview
- Renovate
minimumReleaseAge. Cooldown configuration - pnpm
minimumReleaseAgeExclude. Exclusion list management
This post was written with AI assistance.