Skip to content

feat!: migrate runtime to Vite 8 and native Rolldown optimizer options (#320) - #370

Open
thedavidweng wants to merge 6 commits into
1weiho:mainfrom
thedavidweng:vite-8-migration-21be
Open

feat!: migrate runtime to Vite 8 and native Rolldown optimizer options (#320)#370
thedavidweng wants to merge 6 commits into
1weiho:mainfrom
thedavidweng:vite-8-migration-21be

Conversation

@thedavidweng

@thedavidweng thedavidweng commented Jul 26, 2026

Copy link
Copy Markdown

Issue reference

Implements #320 (roadmap #318).

Stacking note — please read

This PR depends on #369 (React 19 alignment)@vitejs/plugin-react@6 (the release that supports React 19) declares vite: ^8.0.0 as a peer, so React 19 and Vite 8 are coupled. This branch is based on main and includes the React 19 commits from #369. The Vite 8–specific changes are the last 2 commits; the first 3 commits are identical to #369.

For review, please focus on these files (Vite 8 only):

  • packages/core/src/vite/config.ts
  • packages/core/src/vite/config.test.ts
  • packages/core/package.json (the vite and @vitejs/plugin-react lines)
  • packages/cli/template/package.json (the vite line)
  • .changeset/vite-8-migration.md

Once #369 merges, I will rebase this branch onto main and the diff will shrink to only the Vite 8 changes.

Exact scope

Vite 8 + native Rolldown/Oxc optimizer migration only:

  • vite^8.1.4 in @open-slide/core and CLI template
  • @vitejs/plugin-react^6.0.3
  • replace optimizeDeps.esbuildOptions with optimizeDeps.rolldownOptions
  • lockfile (regenerated against current main + React 19)
  • regression test for virtual-module externals
  • changeset

Not enabled: experimental Full Bundle Mode, React Compiler, unrelated refactors.

Versions before and after

Item Before After
packages/core vite ^5.4.10 (resolved 5.4.21) ^8.1.4 (resolved 8.1.4)
packages/core @vitejs/plugin-react ^4.3.3 ^6.0.3
CLI template vite ^5.4.10 ^8.1.4
Optimizer config optimizeDeps.esbuildOptions.plugins optimizeDeps.rolldownOptions.plugins

Vitest still pulls transitive vite@5.4.21 (dev-only) until #322 upgrades Vitest.

Why the old state was a problem

  • Vite 5 is multiple majors behind the current stable line.
  • open-slide relied on optimizeDeps.esbuildOptions.plugins, which Vite 8 only translates with partial support and marks deprecated for removal.
  • Dual esbuild-dev / Rollup-prod pipelines increase module-resolution divergence for virtual modules and pnpm-strict installs.

Why these versions were chosen

  • Current stable Vite 8.1.4.
  • @vitejs/plugin-react 6.0.3 (peer vite ^8, Oxc-based refresh path; React Compiler not enabled).
  • Native rolldownOptions per Vite 8 migration guide — no retained esbuild optimizer compatibility path.

Breaking changes reviewed

  • Vite 5 → 8 majors (Rolldown/Oxc, CJS interop consistency, browser target updates).
  • Generated workspaces require Vite 8.
  • Plugin authors / config consumers must not use optimizeDeps.esbuildOptions with this package.

Source changes required (Vite 8 only)

File Change
packages/core/src/vite/config.ts rolldownOptions virtual-externals plugin
packages/core/src/vite/config.test.ts asserts no esbuildOptions; virtual IDs marked external
packages/core/package.json / template Vite 8 + plugin-react 6
lockfile + changeset

Tests added or changed

  • Added packages/core/src/vite/config.test.ts (virtual externals + no esbuildOptions).
  • Suite: 306 passed.

Benchmark results

Same machine, Node 24.18.0, pnpm 10.17.0. Repository-measured (not upstream Rollup claims):

Metric Before (Vite 5.4.21) After (Vite 8.1.4) Change
pnpm --filter demo build ~4.15s 1.195s −71% (Rolldown)
demo main JS 1,212.23 kB / gzip 357.93 kB 1,171.36 kB / gzip 342.55 kB −40.9 kB

Manual validation results

On Node 24.18.0 with pnpm 10.17.0 (current main toolchain, plus the React 19 base):

  • pnpm install
  • pnpm format:check / pnpm lint / pnpm typecheck / pnpm test (306 passed) / pnpm build
  • demo production build prints vite v8.1.4
  • no optimizeDeps.esbuildOptions in core source ✅
  • Base UI / use-sync-external-store/shim remain in optimizeDeps.include

Known limitations

  1. Includes React 19 commits from feat!: align core, demo, and CLI template on React 19 (#319) #369 (stacking artifact); will rebase onto main after feat!: align core, demo, and CLI template on React 19 (#319) #369 merges.
  2. Vitest 2 still vendors Vite 5 for tests — intentional until chore(tooling): upgrade TypeScript, Vitest, tsdown, Turbo, and repository build tooling #322.
  3. Full interactive HMR/browser matrix not driven locally; production build + unit tests + config contract covered.

Prohibited workarounds — confirmation

Not used: --force, --legacy-peer-deps, overrides/aliases, patch-package, Full Bundle Mode, React Compiler, blanket suppressions, prereleases, unrelated features.

Summary by CodeRabbit

  • New Features
    • Runtime and generated workspaces now require React 19 and Vite 8.
    • Vite dependency optimization now uses native Rolldown support.
  • Bug Fixes
    • Improved MDX image handling by only passing string src values to the zoom image component.
    • Updated navigation/inspector ref typings to support nullable DOM references.
  • Tests
    • Added coverage validating virtual module externalization with the updated Vite configuration.

cursoragent and others added 5 commits July 25, 2026 23:07
Upgrade react/react-dom and matching types to 19.2.x across core,
demo, and the generated template. Update RefObject typings for the
React 19 nullability contract.

Co-authored-by: Davy <thedavidweng@users.noreply.github.com>
React 19 widens HTMLImageElement src to include Blob, which is incompatible
with Next/fumadocs ImageProps. Keep string sources only for ImageZoom.

Co-authored-by: Davy <thedavidweng@users.noreply.github.com>
Upgrade vite to 8.1.4 and @vitejs/plugin-react to 6.x. Replace deprecated
optimizeDeps.esbuildOptions with optimizeDeps.rolldownOptions for virtual
module exclusion. Fix website MDX ImageZoom typing exposed by the lockfile
update.

Co-authored-by: Davy <thedavidweng@users.noreply.github.com>
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

@thedavidweng is attempting to deploy a commit to the open-slide Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR aligns runtime and generated workspaces with React 19 and Vite 8, updates nullable React ref typings, normalizes MDX image sources, and replaces esbuild virtual-module externalization with a tested Rolldown plugin.

Changes

React 19 and Vite 8 alignment

Layer / File(s) Summary
Runtime and template toolchain alignment
.changeset/*, apps/demo/package.json, packages/cli/template/package.json, packages/core/package.json, apps/web/components/mdx.tsx
React, React types, Vite, and the React plugin are upgraded; changesets document major releases, and MDX image handling only forwards string src values to ImageZoom.
Nullable DOM ref contracts
packages/core/src/app/components/inspector/inspect-overlay.tsx, packages/core/src/app/lib/use-*-page-navigation.ts, packages/core/src/app/routes/slide.tsx
Component and navigation ref types now accept nullable DOM references.
Rolldown virtual module externalization
packages/core/src/vite/config.ts, packages/core/src/vite/config.test.ts
Virtual open-slide imports are externalized through a Rolldown resolver, with tests covering configuration shape and resolver results.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Poem

I’m a rabbit with React nineteen,
Hopping through Vite’s Rolldown scene.
Null refs now fit just right,
Virtual slides externalize light.
Binky, build, and test—clean and green!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: migrating the runtime to Vite 8 with native Rolldown optimizer options.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/core/src/vite/config.test.ts (1)

13-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Exercise the actual dependency optimizer in this regression test.

The test calls resolveId directly, so it would still pass if Vite/Rolldown ignored or misordered optimizeDeps.rolldownOptions.plugins. Add a temporary fixture that runs the optimizer or dev-server path and asserts that virtual:open-slide/slides remains external without an unresolved-module failure. (vite.dev)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/vite/config.test.ts` around lines 13 - 38, Extend the test
around createViteConfig to exercise Vite/Rolldown’s actual
dependency-optimization or dev-server execution path using a temporary fixture,
rather than invoking the virtual-externals plugin’s resolveId directly. Assert
that importing virtual:open-slide/slides completes without an unresolved-module
failure and remains external, while preserving the existing configuration
assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/template/package.json`:
- Around line 14-20: Remove the direct dependency-version edits from the
template package.json and apply them through the approved template
source-of-truth or generation flow. If direct template edits are now
intentionally supported, update the prohibition rule instead; keep the generated
template output consistent with the chosen approach.
- Around line 14-20: Update the `@open-slide/core` dependency in
packages/cli/template/package.json from the old ^0.0.6 range to the released 1.x
major compatible with the React 19 and Vite 8 template, matching the major
version scheduled by the changesets and the current packages/core version.

---

Nitpick comments:
In `@packages/core/src/vite/config.test.ts`:
- Around line 13-38: Extend the test around createViteConfig to exercise
Vite/Rolldown’s actual dependency-optimization or dev-server execution path
using a temporary fixture, rather than invoking the virtual-externals plugin’s
resolveId directly. Assert that importing virtual:open-slide/slides completes
without an unresolved-module failure and remains external, while preserving the
existing configuration assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5902bafd-6b15-4de2-a4e2-a5419398a8a6

📥 Commits

Reviewing files that changed from the base of the PR and between c408ba0 and aa2258e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • .changeset/react-19-alignment.md
  • .changeset/vite-8-migration.md
  • apps/demo/package.json
  • apps/web/components/mdx.tsx
  • packages/cli/template/package.json
  • packages/core/package.json
  • packages/core/src/app/components/inspector/inspect-overlay.tsx
  • packages/core/src/app/lib/use-click-page-navigation.ts
  • packages/core/src/app/lib/use-wheel-page-navigation.ts
  • packages/core/src/app/routes/slide.tsx
  • packages/core/src/vite/config.test.ts
  • packages/core/src/vite/config.ts

Comment on lines +14 to +20
"react": "^19.2.7",
"react-dom": "^19.2.7"
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"vite": "^5.4.10"
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"vite": "^8.1.4"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '^(packages/cli/template/package\.json|packages/cli/template/open-slide\.config\.ts|packages/(cli|core)/package\.json|.*\.changeset|.)$' | sed -n '1,120p'

echo
echo "== package manifests relevant deps =="
for f in packages/cli/package.json packages/core/package.json packages/cli/template/package.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    sed -n '1,80p' "$f"
  fi
done

echo
echo "== changesets =="
if [ -d .changeset ]; then
  find .changeset -maxdepth 1 -type f -print -exec sh -c 'echo "--- {} ---"; sed -n "1,120p" "{}"' \;
else
  echo "no .changeset directory"
fi

echo
echo "== git diff summary/name-status =="
git diff --stat
git diff --name-status

Repository: 1weiho/open-slide

Length of output: 5810


Move template package versioning out of direct edits.

packages/cli/template/package.json is covered by the rule prohibiting direct changes to packages/cli/template/**/{package.json,open-slide.config.ts}. Drop these direct edits and update the template via the approved source-of-truth/generation flow, or update that prohibition if it is obsolete.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/template/package.json` around lines 14 - 20, Remove the direct
dependency-version edits from the template package.json and apply them through
the approved template source-of-truth or generation flow. If direct template
edits are now intentionally supported, update the prohibition rule instead; keep
the generated template output consistent with the chosen approach.

Source: Path instructions


🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

node -p "require('./packages/core/package.json').version"
node -p "require('./packages/cli/template/package.json').dependencies['`@open-slide/core`']"
rg -n '"`@open-slide/core`":' .changeset

Repository: 1weiho/open-slide

Length of output: 289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- package.json excerpt ---\n'
sed -n '1,80p' packages/cli/template/package.json

printf '\n--- changesets ---\n'
for f in .changeset/*.md; do
  echo "### $f"
  cat -n "$f"
done

printf '\n--- package manager config relevant files ---\n'
git ls-files | rg '(^|/)(package.json|pnpm-workspace.yaml|biome.json|tsconfig.*\.json)$' | head -80

Repository: 1weiho/open-slide

Length of output: 246


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- packages/cli/template/package.json excerpt ---'
sed -n '1,80p' packages/cli/template/package.json

printf '%s\n' ''
printf '%s\n' '--- changesets ---'
for f in .changeset/*.md; do
  echo "### $f"
  cat -n "$f"
done

printf '%s\n' ''
printf '%s\n' '--- repo files relevant to package manifests/config ---'
git ls-files | rg '(^|/)(package.json|pnpm-workspace.yaml|biome.json|tsconfig.*\.json)$' || true

Repository: 1weiho/open-slide

Length of output: 2409


Publish and update the core major version in the template.

.changeset/react-19-alignment.md and .changeset/vite-8-migration.md both schedule a major @open-slide/core release, but packages/cli/template/package.json still depends on ^0.0.6 while packages/core/package.json is at 1.17.1. Generated workspaces will resolve the old compatibility core against the React 19/Vite 8 template; update this range to the released major built by the changesets.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/template/package.json` around lines 14 - 20, Update the
`@open-slide/core` dependency in packages/cli/template/package.json from the old
^0.0.6 range to the released 1.x major compatible with the React 19 and Vite 8
template, matching the major version scheduled by the changesets and the current
packages/core version.

@thedavidweng

Copy link
Copy Markdown
Author

Addressed CodeRabbit review:

Template package.json (not reverted): Same rationale as #369 — the template must align with React 19 + Vite 8 to avoid dual React copies in generated projects. The @open-slide/core: ^0.0.6 range is pre-existing on main and out of scope for this PR.

config.test.ts nitpick (skipped): The test validates the virtual-externals plugin contract by calling resolveId directly. Spinning up a Vite dev server / dependency optimizer in a unit test would be slow and flaky; the existing Playwright e2e suite (merged in #354) covers the end-to-end build/preview path including virtual module resolution. The unit test's job is to verify the plugin returns the right external marker, which it does.

@thedavidweng

Copy link
Copy Markdown
Author

Context re #344 revert: #344 previously combined React 19 + Vite 8 in one PR and was reverted in #356 due to build/preview issues from virtual slide imports not being externalized during dep optimization. #344 used a static external regex at the rolldownOptions level, which Vite's dep scanner did not consistently honor during pre-bundling.

This PR uses a Rolldown plugin with a resolveId hook (the Rolldown-native equivalent of the old esbuild onResolve plugin) instead. Verified that the revert issue is resolved:

  • Dev server: HTTP 200, virtual:open-slide/slides and virtual:open-slide/config resolve correctly.
  • open-slide build + open-slide preview: both succeed.
  • Generated project (open-slide init → install → build → preview): all pass.

See the comment on #318 for full details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants