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/upgrade/v0-to-v1.md.
close
  • English
  • Upgrading from 0.x to v1

    This document lists all breaking changes from Rslib 0.23 to 1.0. You can use it as a migration reference.

    Upgrade Rslib to v1

    Upgrade @rslib/core to version 1.0:

    package.json
    {
      "devDependencies": {
        "@rslib/core": "^1.0.0"
      }
    }

    Rsbuild v2

    Because Rslib v1 is based on Rsbuild v2, you can check the peerDependencies of the Rsbuild plugins in your project for @rsbuild/core v2 support. We recommend using Taze to upgrade the Rsbuild plugins in your project to their latest versions:

    # Upgrade Rsbuild plugins in the current directory
    npx taze major --include "/rsbuild/" -w
    
    # Or recursively upgrade Rsbuild plugins across the monorepo
    npx taze major --include "/rsbuild/" -w -r

    If your project directly uses Rsbuild configuration or JavaScript APIs, you can refer to the Rsbuild v2 upgrade guide for the related changes.

    Default syntax target update

    When output.target is 'node' and lib.syntax is not configured, Rslib v1 attempts to infer the syntax target from package.json#engines.node.

    For example, the following engines.node:

    package.json
    {
      "engines": {
        "node": "^20.19.0 || >=22.12.0"
      }
    }

    Rslib resolves it to the following syntax target:

    rslib.config.ts
    export default {
      lib: [
        {
          syntax: ['node >= 20.19.0'],
        },
      ],
    };

    If engines.node is missing or no minimum version can be inferred, Rslib continues to use 'esnext'.

    An explicit lib.syntax value takes precedence over automatic inference, so existing configurations are unaffected and you can set it explicitly to override the target inferred from engines.node.

    In addition, Rslib v1 adjusts the Browserslist baselines for es2023 and es2024, and adds the new es2025 target:

    lib.syntaxRslib v0.xRslib v1
    es2023Chrome / Edge 94, Firefox 93, Safari / iOS 16.4, Node.js 16.11Chrome / Edge 110, Firefox 115, Safari / iOS 17, Node.js 20
    es2024Same as esnext, using the latest browser or Node.js versionChrome / Edge 112, Firefox 116, Safari / iOS 17, Node.js 20
    es2025Not supportedChrome / Edge 126, Firefox 132, Safari / iOS 17.4, Node.js 23

    These options only control JavaScript and CSS syntax transformations. They do not inject polyfills for runtime APIs missing from the target environment. The practical impact of the new baselines on JavaScript transformations is limited. The main difference is that Lightning CSS may emit more modern CSS.

    No changes are needed if the new baselines are suitable. To preserve the syntax target behavior from Rslib v0.x:

    • If the project previously used es2023 and needs to retain the more conservative compatibility range:

      rslib.config.ts
      export default {
        lib: [
          {
      -      syntax: 'es2023',
      +      syntax: 'es2022',
          },
        ],
      };
    • If the project previously used es2024 and needs to continue using a dynamic Browserslist target:

      rslib.config.ts
      export default {
        lib: [
          {
      -      syntax: 'es2024',
      +      syntax: 'esnext',
          },
        ],
      };

    Default externalsType update

    For ESM output (format: 'esm'), Rslib v1 changes Rspack's default externalsType: 'module-import' to externalsType: 'modern-module':

    Source syntaxRslib v0.xRslib v1
    Static importEmitted as an ESM importEmitted as an ESM import
    Dynamic import()Remains dynamicRemains dynamic
    CommonJS require() (target: 'node')Emitted as an ESM importUses createRequire()
    CommonJS require() (target: 'web')Emitted as an ESM importPreserves require()

    This change only affects external CommonJS modules loaded with require() when externalsType is not explicitly configured. This includes dependencies externalized through lib.autoExternal, output.autoExternal, or output.externals, as well as Node.js built-ins externalized automatically for target: 'node'. Externals loaded with ESM imports retain their previous behavior and generally require no changes.

    Note that if the output contains an external loaded through createRequire() and is bundled again, the consuming bundler must be able to statically analyze this call. Rsbuild / Rspack projects can enable module.parser.javascript.createRequire. If the change in module-loading semantics is acceptable, you can also consider migrating CommonJS require() calls in the source to ESM imports.

    If only one dependency needs to retain the Rslib v0.x behavior, and its loading semantics are compatible with ESM imports, use the ${externalsType} ${libraryName} syntax in output.externals to use module-import for that dependency:

    rslib.config.ts
    export default {
      lib: [
        {
          output: {
            externals: {
              'some-package': 'module-import some-package',
            },
          },
        },
      ],
    };

    To preserve the Rslib v0.x behavior for all dependencies, set externalsType to module-import through tools.rspack:

    rslib.config.ts
    export default {
      lib: [
        {
          tools: {
            rspack(config) {
              config.externalsType = 'module-import';
            },
          },
        },
      ],
    };

    Enable createRequire() parsing by default

    Rslib v1 enables Rspack's module.parser.javascript.createRequire. Statically analyzable dependencies loaded through the require function returned by createRequire() are included in the bundle unless externalized.

    Rslib v0.x did not analyze these require calls and preserved them in the output. When using createRequire(import.meta.url), relative paths were resolved at runtime from the generated file. For example, a project might compile src/foo/bar.ts to dist/bar.js in a separate build and load it from src/index.ts using the path the file will have in the output:

    src/index.ts
    import { createRequire } from 'node:module';
    
    const require = createRequire(import.meta.url);
    const bar = require('./bar.js');

    Rslib v1 instead resolves relative paths at build time from the source file's directory. In this example, Rslib resolves ./bar.js from the directory containing src/index.ts instead of loading dist/bar.js at runtime. When upgrading, adjust the behavior based on your needs:

    • If the module should be bundled, reference its source file directly:

      src/index.ts
      -const bar = require('./bar.js');
      +const bar = require('./foo/bar.ts');
    • If a specific dependency should not be bundled, declare it as external with output.externals.

    • To preserve all such calls as-is, disable the createRequire parser:

      rslib.config.ts
      export default {
        tools: {
          rspack: {
            module: {
              parser: {
                javascript: {
                  createRequire: false,
                },
              },
            },
          },
        },
      };

    Resource module handling updates

    Rslib v1 changes how ESM output (format: 'esm') handles static assets referenced by new URL(), Web Workers, and Wasm modules.

    Static assets with new URL()

    When building ESM output, Rslib v1 treats statically analyzable local new URL() references as static assets. Consider a source file that references logo.svg:

    src/index.ts
    const logo = new URL('./assets/logo.svg', import.meta.url);

    Rslib v0.x preserved this expression and did not emit logo.svg. Rslib v1 emits the file and rewrites the URL to a relative path that points to it:

    dist/index.js
    const logo = new URL('./static/svg/logo.svg', import.meta.url);

    If the project previously copied these assets through output.copy or a script, remove the corresponding configuration after upgrading to avoid duplicate outputs. In bundleless mode (bundle: false), also exclude assets referenced through new URL() from source.entry to avoid generating an additional JavaScript entry for the same file.

    To restore the Rslib v0.x behavior—preserving all new URL() expressions without having Rslib emit the assets—disable the URL parser:

    rslib.config.ts
    export default {
      tools: {
        bundlerChain(chain, { CHAIN_ID }) {
          chain.module
            .rule(CHAIN_ID.RULE.JS)
            .oneOf(CHAIN_ID.ONE_OF.JS_MAIN)
            .parser({
              url: false,
            });
        },
      },
    };

    For more details, see Static assets - new URL imports.

    Web Workers

    When building ESM output, Rslib v1 parses new Worker(new URL(...)) and treats the referenced local script as a Worker entry. Consider a Worker defined in worker.ts:

    src/index.ts
    new Worker(new URL('./worker.ts', import.meta.url));

    Rslib v0.x preserved this expression and did not build worker.ts from the reference. Rslib v1 builds the Worker and its dependencies, rewrites the URL to the corresponding output path, and adds type: 'module':

    dist/index.js
    new Worker(new URL('./worker.js', import.meta.url), {
      type: 'module',
    });

    If the project previously configured the Worker source as a separate entry and referenced the expected .js output in the source code, remove the entry after upgrading and reference the Worker source file directly:

    rslib.config.ts
     export default {
       source: {
         entry: {
           index: './src/index.ts',
    -      worker: './src/worker.ts',
         },
       },
     };
    src/index.ts
    -new Worker(new URL('./worker.js', import.meta.url));
    +new Worker(new URL('./worker.ts', import.meta.url));

    For more details, see Web Workers.

    Wasm

    Rslib v1 provides two output modes for Wasm modules in ESM output:

    • compile mode: Rslib generates the JavaScript code required to load and instantiate Wasm modules and emits hashed .wasm files.
    • preserve mode: JavaScript retains its .wasm imports, while .wasm files keep their original filenames and source-relative directory structure. These imports must be processed by a downstream bundler or target runtime that supports WebAssembly ESM Integration.

    In bundleless mode, Rslib v0.x generated the JavaScript code required to load and instantiate Wasm modules. Rslib v1 uses preserve mode by default and keeps .wasm imports in JavaScript. To use compile mode instead, configure wasm.mode:

    rslib.config.ts
    export default {
      lib: [
        {
          format: 'esm',
          bundle: false,
          wasm: {
            mode: 'compile',
          },
        },
      ],
    };

    Wasm handling in bundle mode remains unchanged.

    For more details, see Wasm - Output modes.

    @typescript/native-preview support update

    In Rslib v0.x, enabling dts.tsgo caused Rslib to load @typescript/native-preview automatically to generate declaration files.

    Rslib v1 does not load @typescript/native-preview by default. Instead, it resolves typescript from the project root and selects the declaration generation method based on the resolved version. When TypeScript 7+ is detected, Rslib automatically enables dts.tsgo.

    To continue using @typescript/native-preview, explicitly specify its module entry through dts.typescriptPath:

    rslib.config.ts
    import { fileURLToPath } from 'node:url';
    
    export default {
      lib: [
        {
          dts: {
            typescriptPath: fileURLToPath(
              import.meta.resolve('@typescript/native-preview'),
            ),
          },
        },
      ],
    };

    Configuration

    Enable redirect.dts.extension by default

    Rslib v1 enables redirect.dts.extension by default. When bundleless declaration files are generated, import paths automatically gain or replace their extensions with JavaScript file extensions that resolve to the corresponding declaration files.

    For example, when an import path corresponds to foo.d.ts, the generated output changes as follows:

    dist/index.d.ts
    -export type { Foo } from './foo';
    +export type { Foo } from './foo.js';

    If your consuming tools depend on type imports without extensions, or another tool handles extension rewriting, restore the Rslib 0.x behavior:

    rslib.config.ts
    export default {
      lib: [
        {
          redirect: {
            dts: {
              extension: false,
            },
          },
        },
      ],
    };

    If you also configure compilerOptions.paths or dts.alias, check whether the mapped type import paths need to point directly to a concrete declaration entry. See redirect.dts.extension for details.

    Migrate lib.autoExternal

    lib.autoExternal is deprecated in Rslib v1, but has not yet been removed and can still be used.

    We recommend replacing it with Rsbuild's output.autoExternal option:

    rslib.config.ts
     export default {
       lib: [
         {
    -      autoExternal: false,
    +      output: {
    +        autoExternal: false,
    +      },
         },
       ],
     };

    Remove experiments.advancedEsm

    The experiments.advancedEsm option has been removed.

    This option was originally used to generate ESM output that was more suitable for static analysis and supported code splitting. In Rslib v1, this behavior is enabled by default for ESM output, so the option is no longer needed.

    rslib.config.ts
     export default {
       lib: [
         {
    -      experiments: {
    -        advancedEsm: true,
    -      },
         },
       ],
     };

    JavaScript API

    • The type of lib in RslibConfig has changed from LibConfig[] to LibConfig[] | undefined. Omitting lib is equivalent to configuring lib: [{}].
    • The invalid 'none' value has been removed from the mode option of rslib.inspectConfig(). When mode is omitted, it is now inferred from process.env.NODE_ENV: it is 'development' when NODE_ENV is 'development', and 'production' otherwise. When mode is 'development', rslib.inspectConfig() now only outputs configurations for libraries with format: 'mf'.