mrkeyoor.com_
Thu 06 Aug 00:59 UTC
npmCLI & Toolingupdated 05 Aug 2026

rolldown

Rolldown is a JavaScript and TypeScript bundler written in Rust, built by VoidZero (Evan You's company) to become the bundler inside Vite. It keeps Rollup's config shape and plugin interface, so input, output, and plugin hooks look familiar, but the scope is closer to esbuild: it transpiles TypeScript and JSX, handles CommonJS without a plugin, inlines env values with define, and minifies through Oxc, all in native code. The pitch is Rollup compatibility at esbuild-class speed, one tool instead of a rollup-plus-esbuild-plus-terser stack, and its download numbers come largely from Vite adopting it under the hood.

Verdict

The likely future default of the Vite ecosystem and already a strong pick for new library and service builds, with the caveat that it is young and plugin compatibility has edges. Migrating working Rollup or esbuild setups is only worth it when build time actually hurts.

API stability3/5Post-1.0 the core Rollup-shaped API is settled and semver applies, but the project is barely out of beta, options are still being added quickly, and Rollup-compatibility corner cases keep shifting between minors.
Docs4/5rolldown.rs has a clear getting-started guide, a full options reference, and an honest page on differences from Rollup and esbuild, but deep plugin-authoring and troubleshooting docs are thinner than Rollup's decade of accumulated material.
Maintenance5/5Developed full-time by paid VoidZero engineers with pushes daily (last on August 5, 2026), 13.8k stars, and its role as Vite's bundler guarantees continued investment; 376 open issues and PRs reflect heavy usage.
Ecosystem4/5About 89M weekly downloads, mostly as Vite's engine, and it can run many existing Rollup plugins, but its own native plugin ecosystem is young and some popular Rollup plugins still misbehave.

Use it if

  • You bundle libraries or Node services today with Rollup and want the same config style with much faster builds and built-in TS, JSX, and CommonJS handling
  • You are on Vite and want your app and library builds to share one bundler family instead of mixing esbuild for transforms and Rollup for output
  • You want minification, define replacement, and target lowering built in, so a production build needs no terser or babel plugins
  • You maintain a monorepo where bundling time in CI is a real cost and a native-code bundler pays for itself
Skip it if

Setup reality

npm install rolldown is quick, but the real payload arrives through an optionalDependencies trick: a platform-specific @rolldown/binding-* native binary. Copying node_modules between macOS and Linux or running a registry proxy that strips optional deps produces a missing-binding error at startup, and pnpm setups need supportedArchitectures configured to prefetch other platforms. Config migration from Rollup is mostly rename-the-file, but plugin behavior differences show up at runtime, not install time, so budget a test pass over your output. Node 20.19+ or 22.12+ is required, and debugging the Rust core means reading GitHub issues rather than stepping through source.

Patterns

Bundle with a config fileconfig-file

// rolldown.config.ts
import { defineConfig } from 'rolldown'

export default defineConfig({
  input: 'src/index.ts',
  output: {
    dir: 'dist',
    format: 'esm',
  },
})
// run: npx rolldown -c

TypeScript entry points work with zero extra config; rolldown -c picks up rolldown.config.ts or .js from the project root.

Bundle programmaticallyjs-api

import { rolldown } from 'rolldown'

const bundle = await rolldown({
  input: 'src/index.ts',
})
await bundle.write({
  dir: 'dist',
  format: 'esm',
})
await bundle.close()

The API mirrors Rollup: rolldown() resolves and builds the graph, write() emits files; call close() or the native side keeps resources alive.

Bundle a Node servicenode-target

import { defineConfig } from 'rolldown'

export default defineConfig({
  input: 'src/server.ts',
  platform: 'node',
  external: [/^node:/],
  output: {
    dir: 'dist',
    format: 'esm',
  },
})

platform: 'node' sets Node-friendly resolution and keeps builtins external; the regex form of external covers all node: imports at once.

Minify output for productionminify-production

export default defineConfig({
  input: 'src/index.ts',
  output: {
    dir: 'dist',
    minify: true,
    sourcemap: true,
  },
})

Minification is built in via the Oxc minifier, so no terser plugin is needed; it is an output-level option, not a top-level one.

Inline environment valuesdefine-env

export default defineConfig({
  input: 'src/index.ts',
  define: {
    'process.env.NODE_ENV': JSON.stringify('production'),
    __VERSION__: JSON.stringify('1.2.3'),
  },
  output: { dir: 'dist' },
})

Values are substituted as expressions like esbuild's define, so strings must be JSON-stringified or they become identifiers.

Emit ESM and CommonJS from one buildmultiple-formats

import { defineConfig } from 'rolldown'

export default defineConfig([
  {
    input: 'src/index.ts',
    output: { dir: 'dist/esm', format: 'esm' },
  },
  {
    input: 'src/index.ts',
    output: { dir: 'dist/cjs', format: 'cjs' },
  },
])

defineConfig accepts an array of configs like Rollup; CommonJS input is handled natively, no @rollup/plugin-commonjs required.

Rebuild on file changeswatch-mode

import { watch } from 'rolldown'

const watcher = watch({
  input: 'src/index.ts',
  output: { dir: 'dist' },
})

watcher.on('event', (event) => {
  if (event.code === 'BUNDLE_END') console.log('rebuilt')
  if (event.code === 'ERROR') console.error(event.error)
})
// later: await watcher.close()

The watcher event codes follow Rollup's convention; the CLI equivalent is rolldown -c --watch.

Alias import pathspath-alias

export default defineConfig({
  input: 'src/index.ts',
  resolve: {
    alias: {
      '@': new URL('./src', import.meta.url).pathname,
    },
  },
  output: { dir: 'dist' },
})

Aliases live under resolve.alias (closer to Vite than to Rollup's plugin approach); they are not read from tsconfig paths automatically unless tsconfig support is configured.

Use an existing Rollup pluginuse-rollup-plugin

import { defineConfig } from 'rolldown'
import json from '@rollup/plugin-json'

export default defineConfig({
  input: 'src/index.ts',
  plugins: [json()],
  output: { dir: 'dist' },
})

Most standard Rollup plugins work as-is, but each JS hook call crosses into native code; check the compatibility notes before porting plugin-heavy configs.

Write a small transform pluginwrite-plugin

const replaceVersion = {
  name: 'replace-version',
  transform(code, id) {
    if (!id.endsWith('.ts')) return null
    return code.replace(/__BUILD_TIME__/g, JSON.stringify(Date.now()))
  },
}

export default defineConfig({
  input: 'src/index.ts',
  plugins: [replaceVersion],
  output: { dir: 'dist' },
})

Plugin hooks use Rollup's names and semantics (transform, resolveId, load); returning null means the hook passed on the module.

Split dynamic imports into chunkscode-splitting

export default defineConfig({
  input: ['src/main.ts', 'src/admin.ts'],
  output: {
    dir: 'dist',
    format: 'esm',
    chunkFileNames: 'chunks/[name]-[hash].js',
  },
})

Multiple entries and dynamic import() produce shared chunks automatically; naming patterns follow Rollup's entryFileNames and chunkFileNames conventions.

Target browsers with syntax loweringbrowser-target

export default defineConfig({
  input: 'src/app.ts',
  platform: 'browser',
  transform: {
    target: 'es2020',
  },
  output: { dir: 'dist', format: 'esm' },
})

Syntax is lowered by Oxc to the given target, but like esbuild there are no runtime polyfills; missing APIs still need core-js or similar.

Alternatives

PackageRegistryPick it when
rollupnpmYou need the most battle-tested output control and full plugin ecosystem, and build speed is not your bottleneck
esbuildnpmYou want a proven fast bundler with a stable, minimal API and do not need Rollup plugin compatibility
vitenpmYou are building a browser app and want a dev server and framework plugins; recent Vite runs Rolldown internally
tsdownnpmYou are publishing a TypeScript library and want declaration files and sensible defaults on top of Rolldown