For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /guide/basic/output-format.md.
close
  • English
  • Output format

    There are multiple supported output formats for the generated JavaScript files in Rslib: ESM, CJS, UMD, MF, and IIFE. In this chapter, we will introduce the differences between these formats and how to choose the right one for your library.

    ESM / CJS

    Library authors need to carefully consider which module formats to support. Let's understand ESM (ECMAScript Modules) and CJS (CommonJS) and when to use them.

    What are ESM and CJS?

    • ESM:

      ESM stands for ECMAScript modules, which is a modern module system introduced in ES2015 that allows JavaScript code to be organized into reusable, self-contained modules. ESM is now the standard for both browser and Node.js environments, replacing older module systems like CommonJS (CJS) and AMD.

    • CommonJS:

      CJS stands for CommonJS modules, which is a module system used in JavaScript, particularly in server-side environments like Node.js. It was created to allow JavaScript to be used outside of the browser by providing a way to manage modules and dependencies.

    Tip

    Read the Node.js Package Configuration Guide to learn more about ESM and CJS, including file structure, package.json configuration, module interoperability, and best practices.

    Choose module formats

    The choice of module format usually depends on how the package will be consumed. For new packages, prefer pure ESM and add a dual ESM/CJS build only when there is a clear compatibility requirement.

    Prefer pure ESM

    ESM is the standard JavaScript module format. It is supported by modern browsers, Node.js, and mainstream build tools, and enables static analysis and tree shaking. Compared with CommonJS, import and export statements are more concise and easier to read. Additionally, maintaining one format reduces build configuration, package exports, and test combinations.

    If consumers still use CommonJS and package.json#exports allows require() to resolve the ESM entry, they can load a pure ESM package directly with require() on Node.js ^20.19.0 or >=22.12.0, provided that neither the entry nor its dependencies use top-level await. Library authors do not need to publish a separate CJS output only for these consumers:

    const packageExports = require('pure-esm-package');

    Publish dual ESM/CJS for compatibility

    Consider publishing both ESM and CJS when:

    • CommonJS consumers use Node.js versions, tools, or runtimes that cannot load ESM synchronously with require().
    • Consumers explicitly require a separate CJS file.

    Dual formats provide broader compatibility and help consumers migrate gradually to ESM, but require separate builds, export mappings, and tests. Loading both formats can also create separate instances of the same package, leading to inconsistent state or identity checks. Confirm that target consumers need CJS before adding it.

    UMD

    What is UMD?

    UMD stands for Universal Module Definition, a pattern for writing JavaScript modules that can work universally across different environments, such as both the browser and Node.js. Its primary goal is to ensure compatibility with the most popular module systems, including AMD (Asynchronous Module Definition), CommonJS (CJS), and browser globals.

    When to use UMD?

    If you are building a library that needs to be used in both the browser and Node.js environments, UMD is a good choice. UMD can be used as a standalone script tag in the browser or as a CommonJS module in Node.js.

    A detailed answer from StackOverflow: What is the Universal Module Definition (UMD)?

    However, for frontend libraries, you still offer a single file for convenience, that users can download (from a CDN) and directly embed in their web pages. This still commonly employs a UMD pattern, it's just no longer written/copied by the library author into their source code, but added automatically by the transpiler/bundler.

    And similarly, for backend/universal libraries that are supposed to work in Node.js, you still also distribute a commonjs module build via npm to support all the users who still use a legacy version of Node.js (and don't want/need to employ a transpiler themselves). This is less common nowadays for new libraries, but existing ones try hard to stay backwards-compatible and not cause applications to break.

    How to build a UMD library?

    • Set the lib.format to umd in the Rslib configuration file.
    • If the library need to be exported with a name, set lib.umdName to the name of the UMD library.
    • Use output.externals to specify the external dependencies that the UMD library depends on, lib.autoExtension is enabled by default for UMD.

    Examples

    The following Rslib config is an example to build a UMD library.

    • lib.format: 'umd': instruct Rslib to build in UMD format.
    • lib.umdName: 'RslibUmdExample': set the export name of the UMD library.
    • output.externals.react: 'React': specify the external dependency react could be accessed by window.React.
    • runtime: 'classic': use the classic runtime of React to support applications that using React version under 18.
    rslib.config.ts
    import { pluginReact } from '@rsbuild/plugin-react';
    import { defineConfig } from '@rslib/core';
    
    export default defineConfig({
      lib: [
        {
          format: 'umd',
          umdName: 'RslibUmdExample',
          output: {
            externals: {
              react: 'React',
            },
            distPath: './dist/umd',
          },
        },
      ],
      output: {
        target: 'web',
      },
      plugins: [
        pluginReact({
          swcReactOptions: {
            runtime: 'classic',
          },
        }),
      ],
    });

    MF

    What is MF?

    MF stands for Module Federation.

    Module Federation is an architectural pattern for JavaScript application decomposition (similar to microservices on the server-side), allowing you to share code and resources between multiple JavaScript applications (or micro-frontends).

    See Module Federation for more details.

    IIFE

    The iife format stands for "immediately-invoked function expression" and is intended to be run in the browser. Wrapping your code in a function expression ensures that any variables in your code don't accidentally conflict with variables in the global scope. If your entry point has exports that you want to expose as a global in the browser, you can configure that global's name using the global name setting.

    In IIFE format, output.globalObject is set to globalThis by default. The import statements that match externals in the source code will be transformed to access properties through globalThis. You can override output.globalObject to any value.

    When specifying the iife format, the source code and corresponding output are as follows:

    source code
    // parent-sdk is marked as externals
    // externals: ['parent-sdk']
    import { version } from 'parent-sdk';
    alert(version);
    IIFE output
    (
      () => {
        const external_parent_sdk_namespaceObject = globalThis['parent-sdk'];
        alert(external_parent_sdk_namespaceObject.version);
      },
    )();