close
CC 4.0 License

The content of this section is derived from the content of the following links and is subject to the CC BY 4.0 license.

The following contents can be assumed to be the result of modifications and deletions based on the original contents if not specifically stated.

Externals

Externals specify which modules Rspack should not bundle, and instead read directly from implementations provided by the external environment.

For example, if a page already includes React from a CDN, or if a library expects the consumer to install react themselves, you can declare it as an external. This reduces bundle size and avoids shipping the same dependency twice.

This capability is commonly used when building libraries, but it is also useful in applications that integrate CDN assets or rely on dependencies injected by the host environment.

  • Type:
type ExternalItem =
  | string
  | RegExp
  | Function
  | { [x: string]: ExternalItemValue };

type Externals = ExternalItem | ExternalItem[];

Basic usage

For example, if the page already includes Day.js from a CDN, you can declare it as an external to avoid bundling it again:

index.html
<script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
rspack.config.mjs
export default {
  externals: {
    dayjs: 'dayjs',
  },
};

In this case, the dayjs module is removed from the bundle and resolved from the external environment at runtime, so code like this still works:

import dayjs from 'dayjs';

console.log(dayjs().format('YYYY-MM-DD'));

In the configuration above, the key dayjs under externals matches the module specifier in import dayjs from 'dayjs', meaning that module should not be bundled.

The value dayjs is then used to access the global variable at runtime. By default, externalsType is var, which means Rspack reads it from the global scope. In a browser, this usually means accessing window.dayjs.

String

In the example above, the value of externals uses the string form. The meaning of that string depends on externalsType.

In general, the string can represent:

Shorthand syntax

If you only need to declare one external, you can use the shorter form:

rspack.config.mjs
export default {
  externals: 'lodash', // equivalent to externals: { lodash: 'lodash' }
};

Matching rules

String externals use exact matching.

For example, the configuration below matches react-dom, but it does not match subpath imports such as react-dom/client:

rspack.config.mjs
export default {
  externals: {
    'react-dom': 'react-dom',
  },
  externalsType: 'module-import',
};

If you want those subpath imports to be externalized as well, list them explicitly:

rspack.config.mjs
export default {
  externals: {
    'react-dom': 'react-dom',
    'react-dom/client': 'react-dom/client',
  },
  externalsType: 'module-import',
};

If you need to match a family of similar import specifiers, use a regular expression instead.

Specifying the external type

You can also specify the external type explicitly with the ${externalsType} ${libraryName} syntax. This overrides the default value from externalsType.

For example, if the external dependency is provided as an ES module:

rspack.config.mjs
export default {
  externals: {
    react: 'module-import react',
  },
};

string[]

rspack.config.mjs
export default {
  externals: {
    subtract: ['./math', 'subtract'],
  },
};

subtract: ['./math', 'subtract'] allows you select part of a module, where ./math is the module and your bundle only requires the subset under the subtract variable.

When the externalsType is commonjs, this example would translate to require('./math').subtract; while when the externalsType is window, this example would translate to window["./math"]["subtract"];

Similar to the string syntax, you can specify the external library type with the ${externalsType} ${libraryName} syntax, in the first item of the array, for example:

rspack.config.mjs
export default {
  externals: {
    subtract: ['commonjs ./math', 'subtract'],
  },
};

object

Warning

An object with { root, commonjs, commonjs2, amd, ... } is only allowed for library.type: 'umd' and externalsType: 'umd'. It's not allowed for other library targets.

rspack.config.mjs
export default {
  externals: {
    // When `library.type: 'umd'` and `externalsType: 'umd'`, the following format must be strictly followed:
    lodash: {
      root: '_', // indicates global variable
      commonjs: 'lodash',
      commonjs2: 'lodash',
      amd: 'lodash',
    },
  },
};

This syntax is used to describe all the possible ways that an external library can be made available. lodash here is available as lodash under AMD and CommonJS module systems but available as _ in a global variable form. subtract here is available via the property subtract under the global math object (e.g. window['math']['subtract']).

function

  • Type:
    • function ({ context, request, contextInfo, getResolve }, callback)
    • function ({ context, request, contextInfo, getResolve }) => promise

It might be useful to define your own function to control the behavior of what you want to externalize from Rspack. webpack-node-externals, for example, excludes all modules from the node_modules directory and provides options to allowlist packages.

Here're arguments the function can receive:

  • ctx (object): Object containing details of the file.
    • ctx.context (string): The directory of the file which contains the import.
    • ctx.request (string): The import path being requested.
    • ctx.contextInfo (object): Contains information about the issuer (e.g. the layer and compiler)
    • ctx.getResolve: Get a resolve function with the current resolver options.
  • callback (function (err, result, type)): Callback function used to indicate how the module should be externalized.

The callback function takes three arguments:

  • err (Error): Used to indicate if there has been an error while externalizing the import. If there is an error, this should be the only parameter used.
  • result (string | string[] | object | boolean): Describes the external module.
    • string | string[] | object: Describes the external module with the other external formats (string, string[], or object).
    • boolean: Passing true externalizes the dependency using the original request path as the external module name. Passing false tells Rspack to skip the remaining external configuration and bundle the dependency instead.
  • type (string): Optional parameter that indicates the module external type (if it has not already been indicated in the result parameter).

As an example, to externalize all imports where the import path matches a regular expression you could do the following:

rspack.config.mjs
export default {
  externals: [
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        // Externalize to a commonjs module using the request path
        return callback(null, 'commonjs ' + request);
      }

      // Continue without externalizing the import
      callback();
    },
  ],
};

Other examples using different module formats:

rspack.config.mjs
export default {
  externals: [
    function (ctx, callback) {
      // The external is a `commonjs2` module located in `@scope/library`
      callback(null, '@scope/library', 'commonjs2');
    },
  ],
};
rspack.config.mjs
export default {
  externals: [
    function (ctx, callback) {
      // The external is a global variable called `nameOfGlobal`.
      callback(null, 'nameOfGlobal');
    },
  ],
};
rspack.config.mjs
export default {
  externals: [
    function (ctx, callback) {
      // The external is a named export in the `@scope/library` module.
      callback(null, ['@scope/library', 'namedexport'], 'commonjs');
    },
  ],
};
rspack.config.mjs
export default {
  externals: [
    function (ctx, callback) {
      // The external is a UMD module
      callback(null, {
        root: 'componentsGlobal',
        commonjs: '@scope/components',
        commonjs2: '@scope/components',
        amd: 'components',
      });
    },
  ],
};

RegExp

You can also use a regular expression to match modules that should be externalized. Any module specifier that matches the pattern will be excluded from the output bundle.

rspack.config.mjs
export default {
  externals: /react-dom/i,
};

In this example, any module specifier matching react-dom will be externalized, including react-dom and react-dom/client.

Combining syntaxes

Sometimes you may want to use a combination of the above syntaxes. This can be done in the following manner:

rspack.config.mjs
export default {
  externals: [
    {
      // String
      react: 'react',
      // Object
      lodash: {
        commonjs: 'lodash',
        amd: 'lodash',
        root: '_', // indicates global variable
      },
      // [string]
      subtract: ['./math', 'subtract'],
    },
    // Function
    function ({ context, request }, callback) {
      if (/^yourregex$/.test(request)) {
        return callback(null, 'commonjs ' + request);
      }
      callback();
    },
    // Regex
    /^(jquery|\$)$/i,
  ],
};
Warning

Default type will be used if you specify externals without a type e.g. externals: { react: 'react' } instead of externals: { react: 'commonjs-module react' }.

externalsType

  • Type: string
  • Default: 'var'

Specify the default type of externals. amd, umd, system and jsonp externals depend on the output.library.type being set to the same value e.g. you can only consume amd externals within an amd library.

Supported types:

rspack.config.mjs
export default {
  externalsType: 'promise',
};

externalsType.commonjs

Specify the default type of externals as 'commonjs'. Rspack will generate code like const X = require('...') for externals used in a module.

Example

import fs from 'fs-extra';
rspack.config.mjs
export default {
  externalsType: 'commonjs',
  externals: {
    'fs-extra': 'fs-extra',
  },
};

Will generate into something like:

const fs = require('fs-extra');

Note that there will be a require() in the output bundle.

externalsType.global

Specify the default type of externals as 'global'. Rspack will read the external as a global variable on the globalObject.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'global',
  externals: {
    jquery: '$',
  },
  output: {
    globalObject: 'global',
  },
};

Will generate into something like

const jq = global['$'];
jq('.my-element').animate(/* ... */);

externalsType.module

Specify the default type of externals as 'module'. Rspack will generate code like import * as X from '...' for externals used in a module.

Make sure to enable output.module.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  output: {
    module: true,
  },
  externalsType: 'module',
  externals: {
    jquery: 'jquery',
  },
};

Will generate into something like

import * as __rspack_external_jquery from 'jquery';

const jq = __rspack_external_jquery['default'];
jq('.my-element').animate(/* ... */);

Note that there will be an import statement in the output bundle.

externalsType.import

Specify the default type of externals as 'import'. Rspack will generate code like import('...') for externals used in a module.

Example

async function foo() {
  const jq = await import('jquery');
  jq('.my-element').animate(/* ... */);
}
rspack.config.mjs
export default {
  externalsType: 'import',
  externals: {
    jquery: 'jquery',
  },
};

Will generate into something like

var __webpack_modules__ = {
  jquery: (module) => {
    module.exports = import('jquery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jquery'),
  );
  jq('.my-element').animate(/* ... */);
}

Note that there will be an import() statement in the output bundle.

externalsType['module-import']

Specify the default type of externals as 'module-import'. This combines 'module' and 'import'. Rspack will automatically detect the type of import syntax, setting it to 'module' for static imports and 'import' for dynamic imports.

Example

import { attempt } from 'lodash';

async function foo() {
  const jq = await import('jquery');
  attempt(() => jq('.my-element').animate(/* ... */));
}
rspack.config.mjs
export default {
  externalsType: 'module-import',
  externals: {
    lodash: 'lodash',
    jquery: 'jquery',
  },
};

Will generate into something like

import * as __rspack_external_lodash from 'lodash';
const lodash = __rspack_external_jquery;

var __webpack_modules__ = {
  jquery: (module) => {
    module.exports = import('jquery');
  },
};

// webpack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jquery'),
  );
  (0, lodash.attempt)(() => jq('.my-element').animate(/* ... */));
}

Note that there will be an import or import() statement in the output bundle.

When a module is not imported via import or import(), Rspack will use "module" externals type as fallback. If you want to use a different type of externals as fallback, you can specify it with a function in the externals option. For example:

rspack.config.mjs
export default {
  externalsType: "module-import",
  externals: [
    function (
      { request, dependencyType },
      callback
    ) {
      if (dependencyType === "commonjs") {
        return callback(null, `node-commonjs ${request}`);
      }
      callback();
    },
  ]

externalsType['commonjs-import']

Specify the default type of externals as 'commonjs-import'. This combines 'commonjs' and 'import'. Rspack will automatically detect the type of import syntax, setting dynamic import to 'import' and leaving others to 'commonjs'.

This is useful when building a Node.js application that target Node.js version higher than 13.2.0, which supports both import() expressions and require().

Note

commonjs-import type is only available of Rspack, and not applicable for webpack.

Example

import { attempt } from 'lodash';

async function foo() {
  const jq = await import('jquery');
  attempt(() => jq('.my-element').animate(/* ... */));
}
rspack.config.mjs
export default {
  externalsType: 'commonjs-import',
  externals: {
    lodash: 'lodash',
    jquery: 'jquery',
  },
};

Will generate into something like

var __webpack_modules__ = {
  lodash: function (module) {
    module.exports = require('lodash');
  },
  jquery: function (module) {
    module.exports = import('jquery');
  },
};

// Rspack runtime...

async function foo() {
  const jq = await Promise.resolve(/* import() */).then(
    __webpack_require__.bind(__webpack_require__, 'jquery'),
  );
  (0, lodash__rspack_import_0__.attempt)(() =>
    jq('.my-element').animate(/* ... */),
  );
}

Note that there will be an import() statement in the output bundle.

externalsType['node-commonjs']

Specify the default type of externals as 'node-commonjs'. Rspack will import createRequire from 'module' to construct a require function for loading externals used in a module.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'node-commonjs',
  externals: {
    jquery: 'jquery',
  },
};

Will generate into something like

import { createRequire } from 'node:module';

const jq = createRequire(import.meta.url)('jquery');
jq('.my-element').animate(/* ... */);

Note that there will be an import statement in the output bundle.

externalsType.promise

Specify the default type of externals as 'promise'. Rspack will read the external as a global variable (similar to 'var') and await for it.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'promise',
  externals: {
    jquery: '$',
  },
};

Will generate into something like

const jq = await $;
jq('.my-element').animate(/* ... */);

externalsType.self

Specify the default type of externals as 'self'. Rspack will read the external as a global variable on the self object.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'self',
  externals: {
    jquery: '$',
  },
};

Will generate into something like

const jq = self['$'];
jq('.my-element').animate(/* ... */);

externalsType.script

Specify the default type of externals as 'script'. Rspack will load the external as a script exposing predefined global variables with HTML <script> element. The <script> tag would be removed after the script has been loaded.

Syntax

rspack.config.mjs
export default {
  externalsType: 'script',
  externals: {
    packageName: [
      'http://example.com/script.js',
      'global',
      'property',
      'property',
    ], // properties are optional
  },
};

You can also use the shortcut syntax if you're not going to specify any properties:

rspack.config.mjs
export default {
  externalsType: 'script',
  externals: {
    packageName: 'global@http://example.com/script.js', // no properties here
  },
};

Note that output.publicPath won't be added to the provided URL.

Example

Let's load a lodash from CDN:

rspack.config.mjs
export default {
  externalsType: 'script',
  externals: {
    lodash: ['https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js', '_'],
  },
};

Then use it in code:

import _ from 'lodash';
console.log(_.head([1, 2, 3]));

Here's how we specify properties for the above example:

rspack.config.mjs
export default {
  externalsType: 'script',
  externals: {
    lodash: [
      'https://cdn.jsdelivr.net/npm/lodash@4.17.19/lodash.min.js',
      '_',
      'head',
    ],
  },
};

Both local variable head and global window._ will be exposed when you import lodash:

import head from 'lodash';
console.log(head([1, 2, 3])); // logs 1 here
console.log(window._.head(['a', 'b'])); // logs a here
Tip

When loading code with HTML <script> tags, the Rspack runtime will try to find an existing <script> tag that matches the src attribute or has a specific data-rspack attribute. For chunk loading data-rspack attribute would have value of '[output.uniqueName]:chunk-[chunkId]' while external script has value of '[output.uniqueName]:[global]'.

Options like output.chunkLoadTimeout, output.crossOriginLoading and output.scriptType will also have effect on the external scripts loaded this way.

externalsType.this

Specify the default type of externals as 'this'. Rspack will read the external as a global variable on the this object.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'this',
  externals: {
    jquery: '$',
  },
};

Will generate into something like

const jq = this['$'];
jq('.my-element').animate(/* ... */);

externalsType.var

Specify the default type of externals as 'var'. Rspack will read the external as a global variable.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'var',
  externals: {
    jquery: '$',
  },
};

Will generate into something like

const jq = $;
jq('.my-element').animate(/* ... */);

externalsType.window

Specify the default type of externals as 'window'. Rspack will read the external as a global variable on the window object.

Example

import jq from 'jquery';
jq('.my-element').animate(/* ... */);
rspack.config.mjs
export default {
  externalsType: 'window',
  externals: {
    jquery: '$',
  },
};

Will generate into something like

const jq = window['$'];
jq('.my-element').animate(/* ... */);

externalsPresets

  • Type: object

Enable presets of externals for specific targets.

externalsPresets.electron

Type: boolean

Treat common electron built-in modules in main and preload context like electron, ipc or shell as external and load them via require() when used.

externalsPresets.electronMain

Type: boolean

Treat electron built-in modules in the main context like app, ipc-main or shell as external and load them via require() when used.

externalsPresets.electronPreload

Type: boolean

Treat electron built-in modules in the preload context like web-frame, ipc-renderer or shell as external and load them via require() when used.

externalsPresets.electronRenderer

Type: boolean

Treat electron built-in modules in the renderer context like web-frame, ipc-renderer or shell as external and load them via require() when used.

externalsPresets.node

Type: boolean

Treat node.js built-in modules like fs, path or vm as external and load them via require() when used.

externalsPresets.nwjs

Type: boolean

Treat NW.js legacy nw.gui module as external and load it via require() when used.

externalsPresets.web

Type: boolean

Treat references to http(s)://... and std:... as external and load them via import when used. (Note that this changes execution order as externals are executed before any other code in the chunk).

externalsPresets.webAsync

Type: boolean

Treat references to http(s)://... and std:... as external and load them via async import() when used (Note that this external type is an async module, which has various effects on the execution).

Note that if you're going to output ES modules with those node.js-related presets, Rspack will set the default externalsType to node-commonjs which would use createRequire to construct a require function instead of using require().

Example

Using node preset will not bundle built-in modules and treats them as external and loads them via require() when used.

rspack.config.mjs
export default {
  externalsPresets: {
    node: true,
  },
};