Plugins

Customize the build process.

  • Type: Array<RspackPluginInstance | RspackPluginFunction | RspackBuiltinPlugin>
  • Default: []

External plugin

Written in JavaScript and compatible with some of the plugins in the webpack community.

RspackPluginInstance

interface RspackPluginInstance {
  apply: (compiler: Compiler) => void;
}

Among them, the interface provided on Compiler can refer to Plugin API.

usage:

rspack.config.js
class CustomPlugin {
  apply(compiler) {
    // some operations
  }
}

module.exports = {
  plugins: [new CustomPlugin()],
};

RspackPluginFunction

type RspackPluginFunction = (this: Compiler, compiler: Compiler) => void;

usage:

rspack.config.js
function customPlugin(compiler) {
  // some operations
}

module.exports = {
  plugins: [customPlugin],
};

Internal plugins

Integrated within Rspack.

Configuration can be written to be used via import/require:

rspack.config.js
const rspack = require('@rspack/core');

module.exports = {
  // ...
  plugins: [new rspack.XxxPlugin()],
};

Plugins can be written to be used via compiler.webpack.XxxPlugin:

CustomPlugin.js
export class CustomPlugin {
  apply(compiler) {
    new compiler.webpack.XxxPlugin().apply(compiler);
    // ...
  }
}

Internal plugins compatible with webpack

In webpack, these plugins are also exported as internal plugins

EntryPlugin

Add an entry chunk at compile time.

new rspack.EntryPlugin(context, entry, options);
  • context
    • Type: string
    • Description: The path requested by the entry module is resolved from the context path.
  • entry
    • Type: string
    • Description: The path requested by the entry module
  • options
    • Type:
    type EntryOptions = {
      name?: string;
      runtime?: EntryRuntime;
      chunkLoading?: ChunkLoading;
      asyncChunks?: boolean;
      publicPath?: PublicPath;
      baseUri?: string;
      filename?: Filename;
    };

DefinePlugin

This plugin will replace variables in the code with other values or expressions at compile time.

new rspack.DefinePlugin(options);
  • options
    • Type: Record<string, string | boolean | undefined>

When using the following configuration:

rspack.config.js
const rspack = require('@rspack/core');
module.exports = {
  plugins: [
    new rspack.DefinePlugin({
      'process.env.NODE_ENV': "'development'",
      TRUE: true,
      TRUE_STRING: 'true',
      UNDEFINED: undefined,
      UNDEFINED_STRING: 'undefined',
    }),
  ],
};

Input:

if (process.env.NODE_ENV === 'development') {
  console.log('run in development mode');
}

console.log(TRUE === TRUE_STRING);
console.log(UNDEFINED === UNDEFINED_STRING);

Output:

if ('development' === 'development') {
  console.log('run in development mode');
}

fetch('/api/test');

console.log(true === true);
console.log(undefined === undefined);

ProvidePlugin

This plugin will automatically load modules instead of having to import or require them everywhere.

new rspack.ProvidePlugin(options);
  • options
    • Type: Record<string, string | string[]>

When using the following configuration:

const rspack = require('@rspack/core');
module.exports = {
  plugins: [
    new rspack.ProvidePlugin({
      process: [require.resolve('process/browser')],
    }),
  ],
};

Which will convert the following code:

console.log(process.version);

To:

import process from 'process/browser';
console.log(process.version);

BannerPlugin

new rspack.BannerPlugin(options);

Adds a banner to the top or bottom of each generated chunk.

  • options

    • Type:
    type BannerContent = string;
    type BannerRules = string | RegExp | Array<string | RegExp>;
    type BannerPluginOptions = {
      banner: BannerContent;
      entryOnly?: boolean;
      footer?: boolean;
      raw?: boolean;
      test?: BannerRules;
      include?: BannerRules;
      exclude?: BannerRules;
    };
    export type BannerPluginArgument = BannerContent | BannerPluginOptions;
    • Default: undefined
    NameTypeDefaultDescription
    bannerstringundefinedSpecifies the banner, it will be wrapped in a comment.
    entryOnlyboolean|undefinedundefinedIf true, the banner will only be added to the entry chunks.
    footerboolean|undefinedundefinedIf true, banner will be placed at the end of the output.
    rawboolean|undefinedundefinedIf true, banner will not be wrapped in a comment.
    testBannerRules|undefinedundefinedInclude all modules that pass test assertion.
    includeBannerRules|undefinedundefinedInclude all modules matching any of these conditions.
    excludeBannerRules|undefinedundefinedExclude all modules matching any of these conditions.

Add a banner to the top or bottom of each chunk file.

rspack.config.js
module.exports = {
  plugins: [
    new rspack.BannerPlugin({
      banner: 'hello world',
      footer: true,
    }),
  ],
};

HotModuleReplacementPlugin

This plugin is used to add the Hot Module Replacement feature. When added, it will add the runtime modules required for the hot change to the runtime chunk.

new rspack.HotModuleReplacementPlugin();

ProgressPlugin

This plugin can be used to configure the progress bar.

new rspack.ProgressPlugin(options);
  • options
    • Type: { prefix?: string }
    • Default: {}
      NameTypeDefaultDescription
      prefixstring'Rspack'The text will be displayed before the progress bar.

ExternalsPlugin

This plugin can be used to add external dependencies.

new rspack.ExternalsPlugin(type, externals);

SourceMapDevToolPlugin

This plugin enables more fine grained control of source map generation. It is also enabled automatically by certain settings of the devtool configuration option.

new rspack.SourceMapDevToolPlugin(options);
Options
  • test (string RegExp [string, RegExp]): Include source maps for modules based on their extension (defaults to .js, .mjs, and .css).
  • include (string RegExp [string, RegExp]): Include source maps for module paths that match the given value.
  • exclude (string RegExp [string, RegExp]): Exclude modules that match the given value from source map generation.
  • filename (string): Defines the output filename of the SourceMap (will be inlined if no value is provided).
  • append (string function): Appends the given value to the original asset. Usually the #sourceMappingURL comment. [url] is replaced with a URL to the source map file. Path parameters are supported: [chunk], [filename] and [contenthash]. Setting append to false disables the appending.
  • moduleFilenameTemplate (string): See output.devtoolModuleFilenameTemplate.
  • fallbackModuleFilenameTemplate (string): See link above.
  • namespace (string): See output.devtoolNamespace.
  • module = true (boolean): Indicates whether loaders should generate source maps.
  • columns = true (boolean): Indicates whether column mappings should be used.
  • noSources = false (boolean): Prevents the source file content from being included in the source map.
  • publicPath (string): Emits absolute URLs with public path prefix, e.g. https://example.com/project/.
  • fileContext (string): Makes the [file] argument relative to this directory.
  • sourceRoot (string): Provide a custom value for the sourceRoot property in the SourceMap.
Examples

The following examples demonstrate some common use cases for this plugin.

Basic Use Case

You can use the following code to replace the configuration option devtool: inline-source-map with an equivalent custom plugin configuration:

module.exports = {
  // ...
  devtool: false,
  plugins: [new rspack.SourceMapDevToolPlugin({})],
};
Exclude Vendor Maps

The following code would exclude source maps for any modules in the vendor.js bundle:

new rspack.SourceMapDevToolPlugin({
  filename: '[file].map[query]',
  exclude: ['vendor.js'],
});
Host Source Maps Externally

Set a URL for source maps. Useful for hosting them on a host that requires authorization.

new rspack.SourceMapDevToolPlugin({
  append: '\n//# sourceMappingURL=https://example.com/sourcemap/[url]',
  filename: '[file].map[query]',
});

And for cases when source maps are stored in the upper level directory:

project |- dist |- public |- bundle-[hash].js |- sourcemaps |- bundle-[hash].js.map

With the following config:

new rspack.SourceMapDevToolPlugin({
  filename: 'sourcemaps/[file].map',
  publicPath: 'https://example.com/project/',
  fileContext: 'public',
});

Will produce the following URL:

https://example.com/project/sourcemaps/bundle-[hash].js.map

node.NodeTargetPlugin

This plugin is used to external the Node.js built-in modules during bundling, and is used by externalsPresets.node under the hood.

new rspack.node.NodeTargetPlugin();

node.NodeTemplatePlugin

This plugin is used to bundle out Node.js assets, often used with childCompiler.

new rspack.node.NodeTemplatePlugin();

javascript.EnableChunkLoadingPlugin

Enable runtime module bundling for this chunkLoadingType, and is used by output.enabledChunkLoadingTypes under the hood.

new rspack.javascript.EnableChunkLoadingPlugin('import');

library.EnableLibraryPlugin

Enable library format bundling for this libraryType, and is used by output.enabledLibraryTypes under the hood.

new rspack.library.EnableLibraryPlugin('var');

wasm.EnableWasmLoadingPlugin

Enable runtime module bundling for this wasmLoadingType, and is used by output.enabledWasmLoadingTypes under the hood.

new rspack.library.EnableWasmLoadingPlugin('fetch');

electron.ElectronTargetPlugin

This plugin is used to external the Electron built-in modules during bundling, and is used by externalsPresets.electron, externalsPresets.electronMain, externalsPresets.electronRenderer, and externalsPresets.electronPreload under the hood.

new rspack.electron.ElectronTargetPlugin();

container.ModuleFederationPlugin

Stability: Experimental

This plugin implements Module Federation 1.5.

  • implementation

  • runtimePlugins

    • Type: string[]
    • Usage: Provide the plugin required to run Module Federation 1.5, which can extend the behavior and capabilities of Module Federation.
  • name

    • Type: string
    • Usage: Define the unique name exposed to other containers in the current build. This name will exist as a global variable for the remote container.
  • filename

    • Type: string
    • Usage: Specify the filename of the remote container entry file. Other containers will load the exposed modules through this file.
  • runtime

    • Type: string | false
    • Usage: Define the runtime chunk for remote container entry.
  • library

    • Type: LibraryOptions
    • Usage: Define the output format of remote container entry. The default libraryType is "var".
  • shareScope

    • Type: string
    • Usage: Define the namespace for shared dependencies in the current container. By configuring share scopes between different containers, the sharing behavior of modules can be controlled, including determining which modules are shared between different containers. The default share scope is "default".
  • remoteType

    • Type: ExternalsType
    • Usage: Defines how to load remote containers, defaulting to "script", which loads via the <script /> tag.
  • remotes

    • Type:
      type Remotes = (RemotesItem | RemotesObject)[] | RemotesObject;
      type RemotesItem = string;
      type RemotesItems = RemotesItem[];
      interface RemotesObject {
        [k: string]: RemotesConfig | RemotesItem | RemotesItems;
      }
      interface RemotesConfig {
        external: RemotesItem | RemotesItems;
        shareScope?: string;
      }
    • Usage: Definition of the modules and their addresses that will be loaded remotely. The key is the name of the remote container, the value is the global variable name exposed by the remote container and the URL of the remote container entry. You can also specify shareScope to control whether the remote container shares dependencies.
  • exposes

    • Type:
      type Exposes = (ExposesItem | ExposesObject)[] | ExposesObject;
      type ExposesItem = string;
      type ExposesItems = ExposesItem[];
      interface ExposesObject {
        [k: string]: ExposesConfig | ExposesItem | ExposesItems;
      }
      interface ExposesConfig {
        import: ExposesItem | ExposesItems;
        name?: string;
      }
    • Usage: Define how local modules can be referenced by remote containers. The key is the name of the module when referenced as a remote module in the remote container, and the value is the module path relative to the current folder. You can provide a name to specify the name of the exposed local module.
  • shared

    • Type:

      type Shared = (SharedItem | SharedObject)[] | SharedObject;
      type SharedItem = string;
      interface SharedObject {
        [k: string]: SharedConfig | SharedItem;
      }
      interface SharedConfig {
        import?: false | SharedItem;
        eager?: boolean;
        packageName?: string;
        requiredVersion?: false | string;
        shareKey?: string;
        shareScope?: string;
        singleton?: boolean;
        strictVersion?: boolean;
        version?: false | string;
      }
    • Usage: Specify which dependencies should be shared dependencies. This allows multiple micro-frontends to share the same instance of a dependency library to avoid loading the same code repeatedly. It can be an object dictionary where the keys are the names of the shared modules and the values are configuration or version strings. It can also be an array where the array items are the shared package names or configurations.

      The SharedConfig can include the following sub-options:

      • import: Module that should be placed in the share scope of the shared module. If the shared module cannot be found in the share scope of the shared module or the version is invalid, this provided module can be used as a fallback module.
      • eager: If set to true, the shared module will be loaded in the initial chunk instead of being dynamically loaded when used. This means that the shared module will be loaded together with the main entry point regardless of whether it has been used. This can eliminate the delay caused by dynamic loading, but it will increase the size of the initial package. Also, please note that when this configuration is enabled, all provided modules and fallback modules will always be downloaded.
      • packageName: Used to determine the package name and required version from package.json. Configuration is only necessary when the package name cannot be automatically determined based on the request.
      • requiredVersion: Accepts semantic version number. For example, "^1.2.3". Used to set the version range of shared modules. If the module version of the remote container does not meet this range, the module will not be loaded.
      • shareKey: Use this key to search for the requested shared module in the share scope of the shared module. The default is the name of the shared module.
      • shareScope: Define the share scope of the shared module. This allows different builds to use their own share scope independently without conflict. The default share scope is "default".
      • singleton: Ensure that shared modules are only loaded once between different versions, following the singleton pattern. This is necessary for libraries designed to run as singletons, such as React, as it can prevent various issues caused by instantiating multiple library instances.
      • strictVersion: Used to strengthen requiredVersion. If set to true, the shared module must match the version specified in requiredVersion exactly, otherwise an error will be reported and the module will not be loaded. If set to false, it can tolerate imprecise matching.
      • version: Explicitly set the version of the shared module. By default, the version in package.json will be used.

container.ModuleFederationPluginV1

Stability: Experimental

This plugin corresponds to Module Federation 1.0, which is the ModuleFederationPlugin in Webpack.

The configuration is consistent with the ModuleFederationPlugin above, except for the two fields implementation and runtimePlugins.

Rspack's unique internal plugin.

These plugins are Rspack's unique internal plugin and follow the XxxRspackPlugin naming scheme.

HtmlRspackPlugin

This plugin can be used to create html files that are associated with Rspack assets.

new rspack.HtmlRspackPlugin(options);
  • options

    • Type:
    type HtmlRspackPluginOptions = {
      title?: string;
      filename?: string;
      template?: string;
      templateContent?: string;
      templateParameters?: Record<string, string>;
      inject?: 'head' | 'body';
      publicPath?: string;
      scriptLoading?: 'blocking' | 'defer' | 'module';
      chunks?: string[];
      excludedChunks?: string[];
      sri?: 'sha256' | 'sha384' | 'sha512';
      minify?: boolean;
      favicon?: string;
      meta?: Record<string, string | Record<string, string>>;
    };
    • Default: {}
    NameTypeDefaultDescription
    titlestring|undefinedundefinedThe title to use for the generated HTML document.
    filenamestring'index.html'The file to write the HTML to. Defaults to index.html. You can specify a subdirectory here too (eg: pages/index.html).
    templatestring|undefinedundefinedThe template file path.
    templateContentstring|undefinedundefinedThe template file content, priority is greater than template.
    templateParametersRecord<string, string>{}Allows to overwrite the parameters used in the template.
    inject'head'|'body'|undefinedundefinedThe script and link tag inject position in template.
    publicPathstring''The publicPath used for script and link tags.
    scriptLoading'blocking'|'defer'|'module''defer'Modern browsers support non blocking javascript loading ('defer') to improve the page startup performance. Setting to 'module' adds attribute type='module'. This also implies 'defer', since modules are automatically deferred.
    chunksstring[]|undefinedundefinedAllows you to add only some chunks.
    excludedChunksstring[]|undefinedundefinedAllows you to skip some chunks.
    sri'sha256'|'sha384'|'sha512'|undefinedundefinedThe sri hash algorithm, disabled by default.
    minifybooleanfalseControls whether to minify the output.
    faviconstring|undefinedundefinedAdds the given favicon path to the output HTML.
    metaRecord<string, string|Record<string, string>>{}Allows to inject meta-tags.
INFO

For complex HTML configuration requirements, you can use html-webpack-plugin (after v0.3.3) or @rspack/plugin-html (before v0.3.3).

SwcJsMinimizerRspackPlugin

This plugin can be used to compress JS assets.

new rspack.SwcJsMinimizerRspackPlugin(options);
  • options

    • Type:

    For details of each options, please visit here.

    type SwcJsMinimizerRspackPluginOptions = {
      /**
       * @deprecated Deprecated, move to `compress.passes`
       */
      passes?: number;
      /**
       * @deprecated Deprecated, move to `compress.drop_console`
       */
      dropConsole?: boolean;
      /**
       * @deprecated Deprecated, move to `compress.pure_funcs`
       */
      pureFuncs?: Array<string>;
      /**
       * @deprecated Deprecated, move to `mangle.keep_classnames`
       */
      keepClassNames?: boolean;
      /**
       * @deprecated Deprecated, move to `mangle.keep_fnames`
       */
      keepFnNames?: boolean;
      /**
       * @deprecated Deprecated, move to `format.comments`
       */
      comments?: false | 'all' | 'some';
      /**
       * @deprecated Deprecated, move to `format.ascii_only`
       */
      asciiOnly?: boolean;
      extractComments?: boolean | RegExp;
      compress?: TerserCompressOptions | boolean;
      mangle?: TerserMangleOptions | boolean;
      format?: JsFormatOptions & ToSnakeCaseProperties<JsFormatOptions>;
    
      test?: MinifyConditions;
      exclude?: MinifyConditions;
      include?: MinifyConditions;
    };
    
    type MinifyCondition = string | RegExp;
    type MinifyConditions = MinifyCondition | MinifyCondition[];
    
    interface JsFormatOptions {
      /**
       * Currently noop.
       * @default false
       * @alias ascii_only
       */
      asciiOnly?: boolean;
      /**
       * Currently noop.
       * @default false
       */
      beautify?: boolean;
      /**
       * Currently noop.
       * @default false
       */
      braces?: boolean;
      /**
       * - `false`: removes all comments
       * - `'some'`: preserves some comments
       * - `'all'`: preserves all comments
       * @default false
       */
      comments?: false | 'some' | 'all';
      /**
       * Currently noop.
       * @default 5
       */
      ecma?: TerserEcmaVersion;
      /**
       * Currently noop.
       * @alias indent_level
       */
      indentLevel?: number;
      /**
       * Currently noop.
       * @alias indent_start
       */
      indentStart?: number;
      /**
       * Currently noop.
       * @alias inline_script
       */
      inlineScript?: number;
      /**
       * Currently noop.
       * @alias keep_numbers
       */
      keepNumbers?: number;
      /**
       * Currently noop.
       * @alias keep_quoted_props
       */
      keepQuotedProps?: boolean;
      /**
       * Currently noop.
       * @alias max_line_len
       */
      maxLineLen?: number | false;
      /**
       * Currently noop.
       */
      preamble?: string;
      /**
       * Currently noop.
       * @alias quote_keys
       */
      quoteKeys?: boolean;
      /**
       * Currently noop.
       * @alias quote_style
       */
      quoteStyle?: boolean;
      /**
       * Currently noop.
       * @alias preserve_annotations
       */
      preserveAnnotations?: boolean;
      /**
       * Currently noop.
       */
      safari10?: boolean;
      /**
       * Currently noop.
       */
      semicolons?: boolean;
      /**
       * Currently noop.
       */
      shebang?: boolean;
      /**
       * Currently noop.
       */
      webkit?: boolean;
      /**
       * Currently noop.
       * @alias wrap_iife
       */
      wrapIife?: boolean;
      /**
       * Currently noop.
       * @alias wrap_func_args
       */
      wrapFuncArgs?: boolean;
    }
    
    type TerserEcmaVersion = 5 | 2015 | 2016 | string | number;
    interface TerserCompressOptions {
      arguments?: boolean;
      arrows?: boolean;
      booleans?: boolean;
      booleans_as_integers?: boolean;
      collapse_vars?: boolean;
      comparisons?: boolean;
      computed_props?: boolean;
      conditionals?: boolean;
      dead_code?: boolean;
      defaults?: boolean;
      directives?: boolean;
      drop_console?: boolean;
      drop_debugger?: boolean;
      ecma?: TerserEcmaVersion;
      evaluate?: boolean;
      expression?: boolean;
      global_defs?: any;
      hoist_funs?: boolean;
      hoist_props?: boolean;
      hoist_vars?: boolean;
      ie8?: boolean;
      if_return?: boolean;
      inline?: 0 | 1 | 2 | 3;
      join_vars?: boolean;
      keep_classnames?: boolean;
      keep_fargs?: boolean;
      keep_fnames?: boolean;
      keep_infinity?: boolean;
      loops?: boolean;
      negate_iife?: boolean;
      passes?: number;
      properties?: boolean;
      pure_getters?: any;
      pure_funcs?: string[];
      reduce_funcs?: boolean;
      reduce_vars?: boolean;
      sequences?: any;
      side_effects?: boolean;
      switches?: boolean;
      top_retain?: any;
      toplevel?: any;
      typeofs?: boolean;
      unsafe?: boolean;
      unsafe_passes?: boolean;
      unsafe_arrows?: boolean;
      unsafe_comps?: boolean;
      unsafe_function?: boolean;
      unsafe_math?: boolean;
      unsafe_symbols?: boolean;
      unsafe_methods?: boolean;
      unsafe_proto?: boolean;
      unsafe_regexp?: boolean;
      unsafe_undefined?: boolean;
      unused?: boolean;
      const_to_let?: boolean;
      module?: boolean;
    }
    interface TerserMangleOptions {
      props?: TerserManglePropertiesOptions;
      toplevel?: boolean;
      keep_classnames?: boolean;
      keep_fnames?: boolean;
      keep_private_props?: boolean;
      ie8?: boolean;
      safari10?: boolean;
      reserved?: string[];
    }
    interface TerserManglePropertiesOptions {}

SwcCssMinimizerRspackPlugin

This plugin can be used to compress CSS assets.

new rspack.SwcCssMinimizerRspackPlugin();

CopyRspackPlugin

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.

Copies individual files or entire directories, which already exist, to the build directory.

new rspack.CopyRspackPlugin(options);
  • options

    • Type:
    export type CopyRspackPluginOptions = {
      patterns: (
        | string // If input is string, it's the same as { from: `your input string` }
        | {
            from: string;
            to?: string; // Determine based on `from`
            context?: string; // Default to `context` in Rspack config
            toType?: 'dir' | 'file' | 'template'; // Determine based on `from`
            noErrorOnMissing?: boolean; // Default to false
            force?: boolean; // Default to false
            priority?: number; // Default to 0
            globOptions?: {
              caseSensitiveMatch?: boolean; // Default to true
              dot?: boolean; // Default to true
              ignore?: string[]; // ignore specific path
            };
          }
      )[];
    };
    • Default: undefined
    NameTypeDefaultDescription
    fromstringundefinedThe source path of the copy operation, which can be an absolute path, a relative path, or a glob search string. It can refer to a file or a directory. If a relative path is passed, it is relative to the context configuration.
    tostringundefinedThe destination of the copy operation, which can be an absolute path, a relative path, or a template string, such as '[name].[hash][ext]'. If not specified, it is equal to output path.
    contextstringundefinedThis configuration determines how the "from" path is matched and the resulting structure after copying.
    toType'dir'|'file'|'template'undefinedSpecify the type of to, which can be a directory, a file, or a template name in rspack. If not specified, it will be automatically inferred.
    noErrorOnMissingbooleanfalseIgnore error if there are missing files or directories.
    forcebooleanfalseWhether to overwrite the asset if it already exist.
    prioritynumber0When force is set to true, if a matching file is found, the one with higher priority will overwrite the one with lower priority.
    globOptionsobjectundefinedThe configuration for glob queries: caseSensitiveMatch determines whether the matching is case sensitive, and dot determines whether files starting with . are matched. ignore is an array of strings in glob format that can be used to ignore specific paths.

For example:

rspack.config.js
const rspack = require('@rspack/core');
module.exports = {
  entry: './src/index.js',
  plugins: [
    new rspack.CopyRspackPlugin({
      patterns: [
        {
          from: 'file.txt',
        },
      ],
    }),
  ],
};

The result of running with the above configuration would be: "dist/file.txt".

rspack.config.js
const rspack = require('@rspack/core');
module.exports = {
  entry: './src/index.js',
  plugins: [
    new rspack.CopyRspackPlugin({
      patterns: [
        {
          from: 'directory',
        },
      ],
    }),
  ],
};

The result of running with the above configuration would be: files and directories inside directory will be placed at output path.

rspack.config.js
const rspack = require('@rspack/core');
module.exports = {
  entry: './src/index.js',
  plugins: [
    new rspack.CopyRspackPlugin({
      patterns: [
        {
          from: 'directory/**/*',
          to: 'newdirectory',
        },
      ],
    }),
  ],
};

The result of running with the above configuration would be that the directory folder is moved to the newdirectory folder within the output folder, for example dist/newdirectory/directory/foo.