Skip to content

Replace Rollup with Rolldown in build pipeline#708

Draft
mkernohanbc wants to merge 8 commits into
mainfrom
684-rolldown
Draft

Replace Rollup with Rolldown in build pipeline#708
mkernohanbc wants to merge 8 commits into
mainfrom
684-rolldown

Conversation

@mkernohanbc

@mkernohanbc mkernohanbc commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

This PR updates the build pipeline for design-system-react-components to use Rolldown in place of Rollup.

Given the current lack of native CSS bundling support in Rolldown, this change includes a small custom plugin that transforms CSS into JS modules (more or less replicating what was previously done by rollup-plugin-postcss.) We should be able to remove this with a future Rolldown update (see here.)

The direct impacts of this change are:

  • Significantly faster build time (npm run build now completes in ~1 second)
  • c. 25% decrease in total bundle size
  • Net 8 fewer devDependencies (+2 from Rolldown, -10 from Rollup)

Holding this PR in draft for now, pending a bit more investigation of how this changes the final output and figuring out how to test this adequately.

@mkernohanbc mkernohanbc added this to the Components v1.0.0 milestone Jun 12, 2026
@mkernohanbc mkernohanbc self-assigned this Jun 12, 2026
@mkernohanbc mkernohanbc added dependencies Changes or issues affecting dependencies react-components Changes or issues affecting the design-system-react-components package labels Jun 12, 2026
@mkernohanbc mkernohanbc linked an issue Jun 12, 2026 that may be closed by this pull request
@mkernohanbc

Copy link
Copy Markdown
Contributor Author

@ty2k for reference, I had Claude do a detailed comparison of dist output between this branch and the current pipeline. Results below.

Build output comparison: Rollup (main) vs Rolldown (684-rolldown)

JS bundles

main (Rollup) branch (Rolldown) delta
ESM raw 1.5 MB 1.1 MB −27%
ESM gzip 314 KB 238 KB −24%
CJS raw 1.5 MB 1.1 MB −27%
CJS gzip 315 KB 239 KB −24%

Rolldown produces tighter output for this codebase. The reduction comes from more compact code generation and the absence of Rollup's circular-dependency handling overhead from @internationalized/date. No consumer impact — straightforwardly better.

Named exports are identical: both CJS bundles export the same 67 named bindings.


dist/index.d.ts

main (Rollup) branch (Rolldown)
Size 20 KB 178 KB
Re-exports from react-aria-components yes no — all types inlined

The main declaration file is thin: DialogTrigger, MenuSection, MenuSectionHeader, MenuTrigger, SubmenuTrigger, and TooltipTrigger are re-exported by reference directly from 'react-aria-components'. The branch inlines all types into one self-contained file.

For consumers this is a net positive — types resolve without navigating into react-aria-components. Not a breaking change, since react-aria-components is a dependency and is always installed.


Export alias ordering

Two name-collision resolutions differ because rolldown-plugin-dts processes source files in a different order than rollup-plugin-dts.

MenuSectionHeader

// main
export { Header as MenuSectionHeader } from 'react-aria-components';

// branch
export { Header$1 as MenuSectionHeader }; // inlined, suffixed to avoid collision with library's own Header

SvgDashIcon / SvgMinusIcon

// main
export { SvgDashIcon$1 as SvgDashIcon, SvgDashIcon as SvgMinusIcon };

// branch
export { SvgDashIcon, SvgDashIcon$1 as SvgMinusIcon };

In both cases consumers import the same names and receive structurally identical types — both SVG components share the same { id } prop interface. Not a breaking change, but a smoke-test in a consumer TypeScript project is recommended before merging.


CJS wrapper format

// main (Rollup)
'use strict';

// branch (Rolldown)
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });

Rolldown follows Vite's CJS convention of stamping Symbol.toStringTag: "Module" on the exports object instead of leading with 'use strict'. Two consequences:

  1. Object.prototype.toString.call(require('@bcgov/...')) returns [object Module] instead of [object Object]. Most consumer code never does this, but some Jest matchers and older interop utilities check for it.
  2. No top-level 'use strict' directive — functionally fine since all TypeScript source is implicitly strict, but worth noting for Jest environments that rely on CJS strict-mode coercion.

Recommended action: run the unit test suite (npm test) and, if any downstream consumer uses Jest with require(), do a quick sanity check there before merging.

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

Labels

dependencies Changes or issues affecting dependencies react-components Changes or issues affecting the design-system-react-components package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate from Rollup to Rolldown

1 participant