Swapping a bundler is easy. Knowing what you promised your consumers is the hard part.

I migrated two packages of our design system (cortex-core and cortex-react) from Rollup to Rolldown. Before touching the tool, I wrote down the output contract:

  • ESM with preserveModules in dist/esm
  • types generated by tsc in dist/types
  • default.css copied at the end of the build

All of it stayed the same. Rolldown's config API is Rollup-compatible and the copy plugin's buildEnd hook still works. The two config files went from 42 and 45 lines down to 18 and 28.

Two decisions worth recording: I dropped the CJS output, since both packages were already ESM-only, and I now clean dist before building so a stale artifact never gets published.

The cost showed up 13 days later: the mobile Storybook stopped rendering with the new bundle's external packages, and the fix touched the Rolldown configs and added a browser shim to the React Native playground.

Lesson: the contract I wrote covered whoever consumes the library, but not whoever consumes the bundle inside our own playground.

When you change a build tool, which consumer do you forget to list?