Rolldown Status
Rolldown backend: support status and graduation criteria
Updated 2026-06-16 (rolldown 1.0.3). Four of five graduation criteria are met: the rolldown suite gates merges (folded into the
testmatrix across node 22/24/25 + macOS), native DTS landed (PR #208, plan 015), the.rolldown.snapfamily is portable + gating, and the wizard hint dropped "experimental". The only open item is thepackem-rolldownplaceholder package decision (low-urgency; it is private and unpublished).
1. Status today
| Dimension | State | Source |
|---|---|---|
| Wizard label | "fast, native DTS" — the "experimental" qualifier was dropped now that the CI-gating and native-DTS criteria are met (the earlier "falls back to rollup for DTS" clause is also gone). | packages/packem/src/bundler/first-run-wizard.ts:52 |
| CI job | Gating — folded into the test matrix via a bundler: [rollup, rolldown] dimension, so the full rolldown suite runs on node 22/24/25 (ubuntu) + node 22 (macOS) and is required through test-required-check (which needs: [files-changed, test]). The standalone advisory test-rolldown job was removed. | .github/workflows/test.yml (test job, bundler matrix) |
| DTS generation (build) | Routes through rolldown natively when bundler: "rolldown" (PR #208). Rollup is no longer pulled in for the DTS path under rolldown; the @visulima/rollup-plugin-dts virtual-module guard makes emitDtsOnly work under rolldown. | packages/packem/src/packem/index.ts |
| DTS watching | Runs natively through rolldown when rolldown is the bundler — the bundle watcher and the DTS watcher both use the rolldown-native watch path (PR #208). No rollup fallback for the watch DTS path. | packages/packem/src/rollup/watch.ts:278-296, 341 |
packem-rolldown pkg | Empty export {} placeholder. No rolldown-only plugins have landed yet. The package is private ("private": true) and not published — pinned at 1.0.0-alpha.0 while its siblings advance, so it is not released on alpha bumps. | packages/packem-rolldown/src/index.ts, packages/packem-rolldown/package.json |
| Local suite (2026-06-16) | rolldown: 476 passed / 0 failed / 37 skipped (41 files passed, 4 skipped); rollup: 505 passed / 0 failed / 8 skipped. The earlier 5 snapshot failures (absolute worktree paths in externals.test.ts/css.test.ts) are fixed by the normalizeRolldownOutput portability helper. | pnpm run test:bundlers in packages/packem |
2. Graduation criteria (proposed)
Each checkbox is a decision point for the maintainer, not a preset constraint.
-
CI stability: met (2026-06-16). Rather than keep a standalone
test-rolldownjob and add it totest-required-check.needsafter N green runs, the rolldown suite was folded directly into thetestmatrix via abundler: [rollup, rolldown]dimension. Becausetest-required-checkalreadyneeds: [files-changed, test], every rolldown matrix leg (node 22/24/25 + macOS) now gates merges alongside rollup. The flakiness that motivated the advisory carve-out was traced to non-portable snapshots (machine-specific absolute pnpm paths and content-derived chunk hashes) and fixed with a rolldown-onlynormalizeRolldownOutputhelper, so the "20 consecutive green runs" probation is moot — the root cause is resolved, not merely observed-stable. -
Native DTS: met (2026-06-16, PR #208 / plan 015). Rolldown-native DTS generation landed — packem routes the DTS path through rolldown when rolldown is the selected bundler, the rollup-DTS fallback pull-in is gone, and the wizard hint's "falls back to rollup for DTS" clause was dropped. The plan-012 GO path below records how the blocker was cleared.
Plan-012 spike (2026-06-11, on branch
advisor/012-rolldown-dts-spike) returned GO (conditional):@visulima/rollup-plugin-dtsis ~97% rolldown-compatible today (rolldown 1.0.3). The single hard blocker was a one-line virtual-module guard inpackages/rollup-plugin-dts/src/generate.ts:if (id.startsWith("\0"))prevents the plugin'stransformhook from clobbering rolldown's injected\0rolldown/runtime.jsmodule, which previously caused a fatalRUNTIME_MODULE_SYMBOL_NOT_FOUNDerror.Progress (2026-06-11, plan 014 merged): the plugin side is DONE — the virtual-module guard landed, rolldown is declared as an optional peer (+ dev) dependency, the
rollupBuild as rolldownBuildalias misnomer in__tests__/index.test.tsis fixed, and a real rolldown test lane (packages/rollup-plugin-dts/__tests__/rolldown.test.ts, 4 fixtures × bothemitDtsOnlymodes, content assertions) enforces the compat claim. Remaining before this criterion can be ticked (plan 015): updatepackages/packem/src/packem/index.tsandpackages/packem/src/rollup/watch.tsto route DTS through rolldown when rolldown is the selected bundler, and decide on stripping rolldown//#regioncomments from emitted d.ts. -
Snapshot currency: met (2026-06-16). The
.rolldown.snapfamily is now exercised by the gating rolldown matrix legs on every qualifying PR, and the snapshots were made machine/CI-portable (thenormalizeRolldownOutputhelper rewrites absolute pnpm-store paths to<root>and content-derived chunk hashes to[HASH]), so a green CI run now proves currency. Regenerate withPACKEM_TEST_BUNDLER=rolldown pnpm exec vitest run "<path>" -ufrompackages/packem. -
Package decision: decide the fate of
packages/packem-rolldown— either (a) activate it when the first rolldown-only plugin lands and export it fromsrc/index.ts, or (b) delete the placeholder and recreate it when real content exists. The package is already private and unpublished (pinned at1.0.0-alpha.0), so there is no consumer-facing cost either way; keeping the reserved barrel is near-zero overhead. Open, low-urgency. -
Wizard label: met (2026-06-16). The "experimental" qualifier was dropped from the wizard hint in
packages/packem/src/bundler/first-run-wizard.ts:52; it now reads"fast, native DTS". This was the last user-visible graduation signal, and its prerequisites (CI stability + native DTS) were already met.
3. What graduation changes (file-by-line)
All rows below are now DONE.
| Criterion | Status | File / change |
|---|---|---|
| CI stability (criterion 1) | DONE | Achieved differently than originally planned: instead of adding a test-rolldown job to test-required-check.needs, rolldown was folded into the test matrix (bundler dimension), which test-required-check already depends on. |
| Native DTS — wizard hint | DONE | first-run-wizard.ts:52 — the "falls back to rollup for DTS" clause was removed. |
| Native DTS lands | DONE | packages/packem/src/packem/index.ts — the rollup-DTS fallback pull-in and informational log line were removed; DTS routes through rolldown natively (PR #208). |
| Native DTS lands (watch) | DONE | packages/packem/src/rollup/watch.ts — DTS watch under rolldown updated alongside PR #208. |
| Wizard label (criterion 5) | DONE | first-run-wizard.ts:52 — "experimental" qualifier dropped; hint now "fast, native DTS". |
4. Non-goals
The following are explicitly out of scope for rolldown graduation:
- Removing the rollup backend. Rollup remains the default and the full-featured path. Graduation means rolldown reaches feature parity for the common case, not that rollup is deprecated.
- Rolldown-only features. Any capability that rolldown supports but rollup does not (e.g., native module federation, rolldown-specific chunk semantics) is a separate roadmap item, not a graduation blocker.
- Changing the rolldown version pin (
rolldown@1.0.3inpnpm-workspace.yaml). Version upgrades follow the normal dependency process; graduation criteria are feature-based, not version-based.