npm rolldown 1.3.0
v1.3.0

7 hours ago

Important

This is a minor release. It adds experimental support for import attributes, and some changes alter default behavior compared to 1.2.16. Please read Breaking changes before upgrading.

Warning

Vite users: Please do not force rolldown@1.3.0 into Vite with overrides or resolutions yet. Vite 8.3.6 and earlier need changes to work with it. Vite pins its rolldown version, so a normal install is not affected. Please wait for a Vite release that supports Rolldown 1.3.

๐ŸŒŸ Import attributes support (experimental)

Import attributes are the with { ... } part of an import. Node.js and browsers require them for JSON and CSS module scripts, so they are common in code written for these runtimes.

import config from './config.json' with { type: 'json' };
import shader from './shader.glsl' with { type: 'text' };
import wasm from './module.wasm' with { type: 'bytes' };

With experimental.importAttributes:

  • The same file imported with different attributes becomes different modules.
  • type: 'json', 'text' and 'bytes' work without a plugin.
  • Plugins can read the attributes in resolveId, load and transform, and change them in resolveId.
// rolldown.config.js
export default {
  experimental: {
    importAttributes: true,
  },
};

The design follows Rollup 5. The option is off by default, because it changes the id of modules imported with attributes, and plugins that use the id as a file path can break.

Rolldown's dev mode and Vite do not support it yet. See the Import Attributes guide for details and plugin migration.

๐ŸŒŸ Agent-friendly build report (experimental)

With devtools: { mode: 'report' }, Rolldown writes small Markdown and JSON files about each build to node_modules/.rolldown/report/. A coding agent can read the numbers directly, and does not need scripts to parse a large event log. People and CI can use them too.

// rolldown.config.js
export default {
  devtools: { mode: 'report' },
};

The report shows:

  • Time: scan and generate times, plugin timings for each hook, hooks that did no work, and the slowest modules in transform hooks.
  • Chunks: the largest chunks, the reason each chunk exists, and modules in more than one chunk.
  • Modules: import kinds, the most-imported modules, and modules that several entries share.
  • Packages: the largest packages, direct and transitive dependencies, and packages with more than one version.
  • Graph: the initial load of each entry, the chunk import graph, and the retained size of each module.
  • Changes: the difference from the previous build, or from a baseline that you pin.
  • Raw data: stable metric ids in metrics.json, and complete graphs in module-graph.json and chunk-graph.json.

See the Build Report guide for how to read each file and how to use the numbers in CI.

๐ŸŒŸ @rolldown/perf-kit (experimental)

@rolldown/perf-kit is a new package that consumes the data from devtools: { mode: 'report' } and adds its own measurements. An agent or a person can use the processed data to improve LCP, FCP and startup time. A fixed baseline and a check of the rendered output show which changes to keep.

npx @rolldown/perf-kit help

It measures 3 targets:

  • A page: LCP and FCP in a throttled browser (scan). The build needs sourcemaps.
  • A Node.js or Deno server: the time until the server is ready (node-scan).
  • A Cloudflare Worker: the time in global scope (worker-scan).

See the Perf Kit guide for the agent prompts and more details.

We compared an agent alone with an agent using perf-kit on 3 open-source Cloudflare Workers. The prompts, results and steps to reproduce are in perf-kit-worker-startup.

Worker startup per app Cost of one agent run

โš ๏ธ Breaking changes

preserveModules file names now follow Rollup (#11410, #11413)

[name] now keeps non-JS extensions, so data.json becomes data.json.js instead of data.js, and Comp.vue becomes Comp.vue.js instead of Comp.js. Libraries that point exports at the old file names need to update them.

CLI: --input cannot be used together with positional entries (#11445)

rolldown 1.js --input 2.js now fails. Use rolldown 1.js 2.js or rolldown --input 1.js --input 2.js.

๐Ÿฉน Notable fixes

External imports keep their attributes correctly (#11302, #11303)

This applies to every build, with or without experimental.importAttributes. Before, two imports of one external with different attributes became one module, and one import was lost. The legacy assert keyword was also copied to the output, which Node.js 22+ cannot load.

// input (`ext` is external)
import 'ext';
import 'ext' with { type: 'json' };
import data from 'ext2' assert { type: 'json' };

// 1.2.16 output
import 'ext' with { type: 'json' };
import data from 'ext2' assert { type: 'json' };

// 1.3.0 output, with a DEPRECATED_IMPORT_ASSERTION warning
import 'ext';
import 'ext' with { type: 'json' };
import data from 'ext2' with { type: 'json' };

Plugins now see such an external with the attributes in its id, for example ext?attributes=%7B%22type%22%3A%22json%22%7D in this.getModuleIds().


[1.3.0] - 2026-11-05

๐Ÿ’ฅ BREAKING CHANGES

๐Ÿš€ Features

  • perf-kit: measure the deployed site and replay it for local builds (#11215) by @IWANABETHATGUY
  • perf-kit: diagnose chunk loading before FCP and LCP (#11214) by @IWANABETHATGUY
  • import-attributes: keep import attributes away from plugins without the option (#11476) by @shulaoda
  • import-attributes: let a type import attribute beat moduleTypes in the asset and copy plugins (#11309) by @shulaoda
  • import-attributes: pass import attributes to the transform hook (#11308) by @shulaoda
  • import-attributes: pass import attributes to the load hook (#11307) by @shulaoda
  • import-attributes: accept import attributes in this.resolve and this.load (#11306) by @shulaoda
  • import-attributes: pass import attributes to the resolveId and resolveDynamicImport hooks (#11305) by @shulaoda
  • import-attributes: expose experimental.importAttributes and the module id helpers to JS (#11304) by @shulaoda
  • import-attributes: render the import attributes of externals from their module identity (#11303) by @shulaoda
  • import-attributes: make import attributes part of module identity (#11302) by @shulaoda
  • import-attributes: model import attributes and keep them on the import record (#11301) by @shulaoda
  • expose notify APIs (#11380) by @sapphi-red
  • devtools: list the hooks that did no work in the report (#11388) by @IWANABETHATGUY

๐Ÿ› Bug Fixes

  • respect NO_COLOR in error and warning diagnostics (#11499) by @shulaoda
  • rolldown_plugin_vite_import_glob: match negated ** globs from the walk root (#11495) by @shulaoda
  • lazy-barrel: report used lazy barrel uncertain bindings with a dedicated error (#11493) by @shulaoda
  • avoid following output directory symlinks with output.cleanDir (#11494) by @sapphi-red
  • rolldown_plugin_vite_dynamic_import_vars: handle CRLF line breaks in the static import prefix (#11492) by @shulaoda
  • rolldown_plugin_vite_build_import_analysis: ensure unique preload markers (#11157) by @sapphi-red
  • watch: match Rollup for BUNDLE_END output and multi-config watch options (#10348) by @Brooooooklyn
  • rolldown_plugin_vite_dynamic_import_vars: escape import specifier (#11483) by @sapphi-red
  • error: add id, plugin, and frame to native errors (#9979) by @raminjafary
  • treeshaking: run a CommonJS module that is reached only through export * (#11423) by @magurotuna
  • escape URL in sourceMappingURL (#11482) by @sapphi-red
  • rolldown_plugin_vite_import_glob: escape import names (#11486) by @sapphi-red
  • rolldown_plugin_esm_external_require: escape import specifiers (#11487) by @sapphi-red
  • tree-shaking: drop unused imports of side-effect-free externals in ESM output (#11470) by @hyfdev
  • lazy-barrel: treat bindings behind skipped lazy barrel records as unknown (#11448) by @shulaoda
  • rolldown_plugin_vite_react_refresh_wrapper: escape import specifier (#11485) by @sapphi-red
  • devtools: count only hook calls that ran in the report (#11468) by @IWANABETHATGUY
  • rust: harden bundle close lifecycle (#11371) by @Brooooooklyn
  • strict-execution-order: name shared CJS re-export bindings independently of load order (#11206) by @natew
  • dev/lazy: don't proxy plugin-resolved externals (#11295) by @cestercian
  • rolldown_plugin_vite_transform: report oxc transformer warnings as warnings (#11459) by @Dunqing
  • dev: report a lazy-compile failure as diagnostics, not a formatted string (#10490) by @tbvjaos510
  • binding: stop mishandling per-call data at the callable builtin plugin boundary (#10482) by @hyfdev
  • dev/lazy: resolve import() of a CommonJS module to its ESM view (#11020) by @h-a-n-a
  • dev/lazy: load a lazy route in one request and only as factories (#11000) by @h-a-n-a
  • error when one module id resolves as both external and non-external (#11421) by @IWANABETHATGUY
  • sourcemap: keep only traced sources and names in module sourcemaps (#11270) by @IWANABETHATGUY
  • give module namespace objects a null prototype and make them non-extensible (#11428) by @IWANABETHATGUY
  • watch: reset JS load promises before rebuilding (#11316) by @owjs3901
  • new-url: keep the query and fragment when rewriting new URL() (#11420) by @theRizwan
  • dev: don't panic when buildStart emits a chunk during a partial rebuild (#11322) by @RagedPanda
  • treeshaking: drop an unused top-level import() of a side-effect-free module that exports then (#11409) by @hyfdev
  • derive reference ids from stable seeds for deterministic builds (#10797) by @MarshallOfSound
  • rolldown_plugin_vite_import_glob: resolve aliased globs without blocking a runtime worker (#11385) by @shulaoda
  • preserve-modules: read the extension after sanitizeFileName like Rollup (#11413) by @IWANABETHATGUY
  • rolldown_plugin_vite_dynamic_import_vars: await the resolver instead of blocking a runtime worker (#11386) by @shulaoda
  • cli: preserve entry arguments after double dash (#11438) by @shuvroroy
  • treeshaking: invalidate constants when exports is reassigned (#11430) by @shuvroroy
  • plugin: queue onLog callbacks eagerly (#11374) by @Brooooooklyn
  • avoid inferring constants from compound CommonJS exports (#11429) by @shuvroroy
  • json: avoid shadowing JSON.parse with named exports (#11432) by @shuvroroy
  • watcher: prioritize queued input during debounce (#11369) by @Brooooooklyn
  • replace: preserve declarations after Unicode text (#11435) by @shuvroroy
  • treeshaking: don't drop side effects that follow an exports.x write in the same CommonJS statement (#11408) by @hyfdev
  • don't inline a CommonJS export that is assigned conditionally or also through module.exports (#11404) by @hyfdev
  • json: preserve proto as an own data property (#11367) by @shuvroroy
  • tree-shaking: preserve dynamic import exports read through callback arguments (#11366) by @shuvroroy
  • respect externalLiveBindings for star re-exports from externals in cjs (#11328) by @logaretm
  • preserve-modules: keep non-JS extensions in [name] (#11410) by @cestercian
  • treeshaking: don't tree-shake a statement that holds a CommonJS top-level return (#11402) by @hyfdev
  • don't export JSON keys that the finalizer inlines away from a shared chunk (#11396) by @IWANABETHATGUY
  • sourcemap: support toUrl without Buffer (#11370) by @Brooooooklyn
  • handle nullish thrown values in error summary (#11373) by @Brooooooklyn
  • don't inline a var that module-level code reads before its declaration (#11379) by @hyfdev
  • treat a repeated var declaration as a reassignment (#11378) by @hyfdev

๐Ÿšœ Refactor

๐Ÿ“š Documentation

  • add build report and perf-kit in-depth pages (#11480) by @IWANABETHATGUY
  • rolldown_plugin_vite_import_glob: describe how import.meta.glob follows file changes (#10573) by @shulaoda
  • import-attributes: add an in-depth guide for import attributes (#11310) by @shulaoda
  • import-attributes: correct comments and docs about import attributes (#11477) by @shulaoda
  • rolldown: explain why drops are deferred and why drain waits for every bundler's drops (#11455) by @hyfdev

โšก Performance

  • rolldown_plugin_vite_dynamic_import_vars: avoid string allocation for first_quasi (#11484) by @sapphi-red
  • node: read each rendered chunk's binding fields once (#11364) by @mattlewis92

๐Ÿงช Testing

  • import-attributes: run the esbuild import attributes tests with the option on (#11472) by @shulaoda
  • import-attributes: port the Rollup 5 import attributes tests (#11381) by @shulaoda
  • rolldown_plugin_vite_import_glob: cover the glob matcher (#10572) by @shulaoda
  • rolldown_plugin_vite_import_glob: cover import.meta.glob file creation and deletion (#10551) by @shulaoda

โš™๏ธ Miscellaneous Tasks

โค๏ธ New Contributors

Don't miss a new rolldown release

NewReleases is sending notifications on new releases.