Skip to content

build(deps): upgrade Vite 7 → 8.0.2 (Rollup → Rolldown)#1347

Draft
iOvergaard wants to merge 10 commits intomainfrom
v2/build/vite-8-upgrade
Draft

build(deps): upgrade Vite 7 → 8.0.2 (Rollup → Rolldown)#1347
iOvergaard wants to merge 10 commits intomainfrom
v2/build/vite-8-upgrade

Conversation

@iOvergaard
Copy link
Copy Markdown
Contributor

@iOvergaard iOvergaard commented Mar 19, 2026

Summary

Upgrades Vite 7 → 8.0.2, which switches the bundler from Rollup to Rolldown. Rolldown has two behavioral differences from Rollup that broke UUI's custom element registration — both are fixed here.

What works end-to-end after this PR

Barrel import registers all components:

import '@umbraco-ui/uui'; // all 81 components are defined in the custom element registry

Cherry-pick import works as expected:

import { UUIButtonElement } from '@umbraco-ui/uui/components/button/button.js';

All 946 tests pass (including 2 new registration smoke tests). Build produces 282 modules.


Fix 1 — Rolldown ignores extglob in sideEffects (package.json)

Rolldown cannot parse the extglob syntax !(*.element).ts used in package.json#sideEffects. When no patterns match, Rolldown treats every file as side-effect-free and drops the bare registration imports (e.g. import "./components/button/button.js") from dist/index.js — so defineElement is never called and no components are registered.

Fix: replace extglob with negative-prefix globs, and move build-time side-effect configuration into vite.config.ts where it belongs.

The sideEffects field in package.json is a public contract for consumer bundlers — it should only reference files that are actually published (dist/). The old config also included src/ patterns which Rolldown reads during the build to decide whether to preserve bare side-effect imports in the output. Rather than encoding build behaviour in package metadata, the fix uses treeshake: { moduleSideEffects: true } in rolldownOptions to tell Rolldown to preserve all module side effects during the build.

Result: package.json#sideEffects is now 4 lines that only describe published dist/ files.

Fix 2 — Rolldown strips re-exports from non-entry modules (vite.config.ts)

When only src/index.ts is an explicit entry, Rolldown resolves re-export chains and strips exports from intermediate registration files like button.js (since UUIButtonElement is reachable via button.element.js). This breaks the cherry-pick import pattern.

Fix: add all component registration files as explicit Rolldown entry points via a componentEntries glob in vite.config.ts. Rolldown then treats each registration file as a first-class output, preserving its exports.

Build verification (scripts/verify-build.js)

A post-build verification script runs in CI after npm run build to catch silent regressions. The build can succeed while producing broken output (e.g. missing bare imports = components won't register). The script checks:

  • dist/index.js has exactly 3 bare side-effect imports
  • dist/components/index.js has 81 registration imports, 0 element imports
  • Registration files have defineElement + exports (cherry-pick pattern)
  • Element files do NOT call defineElement (separation preserved)
  • Lit is externalized (not inlined)
  • Source export count matches component folder count

Registration smoke test (src/components/components.test.ts)

A vitest browser test that verifies:

  • Importing a .element.js file does NOT register the custom element
  • Importing the barrel registers all components

Changes in this PR

File Change
package.json sideEffects: extglob → negative-prefix globs, dist/-only. Vite 7→8.0.2, vitest 4.0→4.1. Add verify-build script
vite.config.ts rollupOptionsrolldownOptions, add componentEntries glob as explicit entries, add treeshake: { moduleSideEffects: true }
scripts/verify-build.js New: post-build verification (17 assertions)
src/components/components.test.ts New: registration smoke test
.github/workflows/tests.yml Run verify-build after build step
package-lock.json Lockfile update (Rollup binaries → Rolldown binaries)

Note: the src/components/index.ts barrel extraction and plop template fixes were cherry-picked to main separately.

Test plan

  • npm run build completes without errors (282 modules, Vite 8.0.2)
  • npm run verify-build — 17/17 checks pass
  • npm run test — 946/946 tests pass in Chromium (including 2 new registration tests)
  • Browser-verified: customElements.get('uui-button') returns UUIButtonElement after barrel import

🤖 Generated with Claude Code

- Bump vite 7.3.1 → ^8.0.1
- Bump vitest ^4.0.18 → ^4.1.0
- Rename `rollupOptions` → `rolldownOptions` in vite.config.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 19, 2026 14:04
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

@iOvergaard iOvergaard added dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code labels Mar 19, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Upgrades the repo’s build/test toolchain to Vite 8 (which switches bundling to Rolldown) and updates Vitest accordingly, aligning the Vite config with the new bundler option name.

Changes:

  • Upgrade vite to ^8.0.1 and vitest / @vitest/browser* to ^4.1.0.
  • Update vite.config.ts to use rolldownOptions instead of rollupOptions.
  • Refresh package-lock.json to reflect the new dependency graph (Rolldown bindings, lightningcss, etc).

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.

File Description
vite.config.ts Switches build bundler configuration to rolldownOptions for Vite 8.
package.json Bumps Vite/Vitest-related devDependency versions to match the new toolchain.
package-lock.json Locks updated dependency tree after upgrading Vite/Vitest (including Rolldown + new transitive deps).

@iOvergaard iOvergaard marked this pull request as draft March 19, 2026 14:24
…istration

Rolldown (Vite 8) has two behavioral differences from Rollup that break
the registration file pattern (button.ts calling defineElement):

1. **Extglob not supported in sideEffects**: The existing
   `!(*.element).ts` extglob patterns in package.json#sideEffects are
   not parsed by Rolldown. With no files matching, Rolldown treats all
   files as side-effect-free and omits the bare registration imports
   (e.g. `import "./components/button/button.js"`) from dist/index.js.

   Fix: replace extglob with negative-prefix glob patterns that Rolldown
   understands (`!dist/components/**/*.element.js` + `dist/**/*.js`).

2. **Re-exports stripped from non-entry modules**: When only src/index.ts
   is the entry, Rolldown resolves re-export chains and strips the
   exports from intermediate modules like button.js (since UUIButtonElement
   is already reachable via button.element.js). This breaks the cherry-pick
   import pattern where consumers do:
     import { UUIButtonElement } from '@umbraco-ui/uui/components/button/button.js'

   Fix: add all component registration files as explicit Rolldown entry
   points via a glob in vite.config.ts. This signals to Rolldown that
   each registration file is a first-class output, preserving its exports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@iOvergaard iOvergaard marked this pull request as ready for review March 25, 2026 11:30
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

Moves the 81 component re-exports out of src/index.ts into a dedicated
src/components/index.ts, keeping src/index.ts slim (3 lines + comment).

Also adds src/components/index.ts as an explicit Rolldown entry in
vite.config.ts (same reason as component registration files — prevents
Rolldown from flattening its re-export chain) and updates the plop
template to append new components to src/components/index.ts instead
of src/index.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

@iOvergaard iOvergaard changed the title build(deps): upgrade Vite 7 → 8 (Rollup → Rolldown) build(deps): upgrade Vite 7 → 8.0.2 (Rollup → Rolldown) Mar 25, 2026
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

iOvergaard and others added 2 commits March 25, 2026 14:55
…kage.json

Replace src/ patterns in package.json#sideEffects with
treeshake.moduleSideEffects: true in rolldownOptions. The sideEffects
field is a public contract for consumer bundlers — it should only
describe published dist/ files, not src/ files that are never shipped.
Build-time side-effect behaviour belongs in the build config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

Pure re-export barrel, same as dist/internal/index.js which was
already excluded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

@iOvergaard
Copy link
Copy Markdown
Contributor Author

Follow-up to watch: Rolldown rc.12 was released today with two potentially relevant changes:

  • #8624 — Side effect detection migrated to Oxc's MayHaveSideEffects trait (more accurate inference). The treeshake: { moduleSideEffects: true } override in vite.config.ts may become redundant.
  • #8895 — "load import-then-export specifiers when barrel has local exports" in the lazy-barrel feature. This sounds like it may fix the root cause of why componentEntries explicit entries are needed.

When Vite ships with rc.12, worth re-testing whether either of those workarounds can be dropped.

@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

- scripts/verify-build.js: post-build assertions that catch silent
  regressions (missing bare imports, broken registration/element
  separation, source/dist count mismatch). Runs in CI after build.
- src/components/components.test.ts: vitest browser smoke test that
  verifies element-only import does NOT register, and barrel import
  registers all components.
- .github/workflows/tests.yml: run verify-build after build step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-beach-055ecb503-1347.westeurope.azurestaticapps.net

@iOvergaard iOvergaard marked this pull request as draft April 20, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants