Rolldown

repository·main·Indexed 11 days ago

https://github.com/rolldown/rolldown

A high-performance JavaScript/TypeScript bundler written in Rust, designed to eventually power Vite. It combines the Rollup-compatible plugin ecosystem with the performance and scope characteristics of esbuild.

Tokens
151.4K
Snippets
341
Records
755
Agent score
93%

What's inside Rolldown

  1. Overview of Rolldown

    main

    Rolldown is a high-performance, Rust-based bundler for JavaScript. It is designed to provide Rollup-compatible APIs while aiming for esbuild feature parity.

    Key use cases include:

    • Vite Integration: It is primarily designed to serve as the underlying bundler for Vite, aiming to unify the build toolchain by replacing both esbuild and Rollup.
    • Standalone Bundling: It can be used as a general-purpose bundler.
    • Rollup Replacement: It serves as a drop-in replacement for Rollup in most scenarios.
    • esbuild Alternative: It can be used when more granular control over chunking is required compared to esbuild.
  2. What is Rolldown?

    main

    Rolldown is a high-performance JavaScript/TypeScript bundler written in Rust. It is designed to be the future bundler for Vite.

    Key characteristics:

    • Rollup Compatibility: Provides Rollup-compatible APIs and a plugin interface.
    • esbuild-like Scope: While maintaining Rollup compatibility, its scope and performance characteristics are intended to be more similar to esbuild.
    • High Performance: Built in Rust to provide fast bundling capabilities.
  3. Use the rolldown-vite data-url plugin

    main

    The rolldown-vite data-url plugin enables loading data: URIs as virtual modules in JavaScript, CSS, and JSON contexts.

    Note: This plugin is exclusive to rolldown-vite and is not recommended for external use.

    Supported MIME types:

    • text/css → loaded as CSS module
    • text/javascript → loaded as JS module
    • application/json → loaded as JSON module

    Other MIME types are ignored and fall back to default behavior.

  4. Understand the Rolldown repository structure

    main

    The Rolldown repository is organized into several top-level directories based on the runtime and purpose of the code:

    • /crates: Contains all Rust-based crates, including the core bundler logic (/rolldown), Node.js bindings (/rolldown_binding), and Rust benchmarks (/bench).
    • /packages: Contains Node.js packages, including the main @rolldown/rolldown package, Node.js benchmarks (/bench), and testing adapters like /rollup-tests and /vite-tests.
    • /examples: Provides practical usage examples for using Rolldown in Node.js across different scenarios.
    • /scripts: Automation scripts for project tasks.
    • /web: Project-related websites, including the official documentation located in /web/docs.
    • /vite: A specialized, gitignored clone of the Vite repository used for testing compatibility. Note: Do not edit files within this directory.
  5. What is Rolldown devtools?

    main
    Rolldown devtools is a tracing-based system designed to emit structured build-time data to disk. This data includes module graphs, chunk graphs, plugin hook calls, and generated assets. The primary purpose is to allow external tools (such as Vite devtools) to consume this data to provide debugging, profiling, and visualization experiences for the build process.
  6. What is a barrel module?

    main

    A barrel module is a pattern where a single module (often an index.js file) re-exports functionality from multiple other modules. This is used to create a cleaner, centralized public API for a package or directory, allowing consumers to import multiple entities from a single entry point rather than specifying individual file paths.

    Example of a barrel module (components/index.js):

    export { Button } from './Button';
    export { Card } from './Card';
    export { Modal } from './Modal';
    export { Tabs } from './Tabs';

    How to consume a barrel module:

    import { Button, Card } from './components';

    Note on Performance: Traditionally, barrel modules can cause performance issues because bundlers may need to compile all re-exported modules even if only a few are used. Rolldown provides Lazy Barrel Optimization to mitigate this.

    // components/index.js (barrel module)
    export { Button } from './Button';
    export { Card } from './Card';
    export { Modal } from './Modal';
    export { Tabs } from './Tabs';
    
    // Consumer usage
    import { Button, Card } from './components';
  7. What is PIFE and how does it affect optimization?

    main

    PIFE stands for "Possibly-Invoked Function Expressions". These are function expressions wrapped in parentheses, such as (function() { ... })().

    In the context of Rolldown and JavaScript engine optimization, PIFEs annotate functions that are likely to be invoked eagerly. When the V8 JavaScript engine (used in Chrome and Node.js) encounters these expressions, it performs eager compilation rather than waiting to compile them later, which can improve performance.

  8. Overview of Rolldown's cache mechanisms

    main

    Rolldown utilizes several distinct cache mechanisms to optimize performance and support features like incremental builds and Hot Module Replacement (HMR). The primary mechanism is ScanStageCache, which acts as a bundler-level snapshot of the parsed module graph.

    Other cache types include:

    • Incremental-build cache: The central ScanStageCache for module-graph snapshots.
    • Cross-build invalidation state: Data that persists alongside the incremental cache to help determine what to invalidate (e.g., transform_dependencies and module_infos).
    • Within-build memoization: Transient caches used during a single build process (e.g., SideEffectCache, TsconfigCache).
    • Plugin scratch state: Shared maps stored in PluginContext.meta() that allow data to pass between different plugin hook invocations.
    • JS-side cache: Data held on the JavaScript side, such as PluginContextData.
    • Watch-mode filesystem cache: Metadata used by the filesystem watcher for event debouncing.
  9. Use Span for locations and NodeId for identity

    main

    When working with AST nodes, distinguish between their location and their identity:

    Use Span for:

    • Diagnostics and warnings (pointing to user source).
    • Comments, source-map ranges, and directive/hashbang ranges.
    • Generated replacement spans (to preserve source location during codegen).
    • Import-record source locations (e.g., importer_span for TLA import-chain diagnostics).

    Use NodeId for:

    • Identifying the same AST node across different compiler passes.
    • Keying side tables for rewrites or metadata lookups.

    Warning: Do not add a cross-pass node side table keyed only by Span. If a later pass needs to identify the same AST node, use NodeId.

  10. Understand BundleMode and incremental build states

    main

    Rolldown uses the BundleMode enum to manage how the ScanStageCache (the cache used during the module scanning stage) is handled across builds. This determines whether the bundler performs a fresh scan, reuses existing cache, or persists the cache for future use.

    ModeScanStageCache inScanStageCache outShared state resetUse case
    FullBuildNoneDiscardedYesOne-shot build, non-incremental watch
    IncrementalFullBuildFreshSavedYesFirst build with incremental: true, or dev-mode recovery after a failed build
    IncrementalBuildExistingUpdatedNoSubsequent builds with incremental: true

    Key distinction: Use IncrementalFullBuild when you want to start a fresh scan but ensure the resulting cache is saved for subsequent IncrementalBuild calls. Use FullBuild for one-off builds where no cache persistence is required.

    pub enum BundleMode {
        FullBuild,              // Fresh ScanStageCache for this build; discard it afterward.
        IncrementalFullBuild,   // Fresh ScanStageCache for this build; retain it for later incremental builds.
        IncrementalBuild,       // Reuse existing ScanStageCache; only rescan changed files.
    }