CC 4.0 协议声明

本节内容派生于以下链接指向的内容 ,并遵守 CC BY 4.0 许可证的规定。

以下内容如果没有特殊声明,可以认为都是基于原内容的修改和删减后的结果。

Output

顶级的 output 包含一组选项,指导 Rspack 如何以及在哪里输出 bundles、assets,以及使用 Rspack 打包或加载的任何其他内容。

  • 类型: Object

output.assetModuleFilename

  • 类型: string | ((pathData: PathData, assetInfo?: JsAssetInfo) => string)
  • 默认值: '[hash][ext][query]'

output.filename 类似,但适用于资源模块

[name][file][query][fragment][base][path] 在使用数据 URI 替换构建的资源中被设置为空字符串。

Asset module 输出的文件名称。这个值可以被 Rule.generator.filename 覆盖。

Asset module 作为一个单独的文件输出的情况

output.asyncChunks

  • 类型: boolean
  • 默认值: true

是否创建按需加载的异步 chunk。

output.charset

  • 类型: boolean
  • 默认值: true

<script> 标签添加 charset="utf-8" 属性。

TIP

尽管 <script> 标签的 charset 属性已被标记为已废弃的, 为了兼容旧浏览器,在默认情况下 rspack 依然会添加该属性。

output.chunkFilename

  • 类型: string = '[id].js' | (pathData: PathData, assetInfo?: JsAssetInfo) => string
  • 默认值:output.filename 不为函数时,推断 output.filename 推断;否则为 '[id].js'

这个选项决定了非初始块文件的名称。有关可能值的详细信息,请参见 output.filename 选项。

注意,这些文件名需要在运行时生成,以便发送 chunk 的请求。因此,像 [name][chunkhash] 这样的占位符需要在 Rspack 运行时将 chunk id 映射到占位符值添加到输出 bundle 中。这会增加大小,并且可能会在任何 chunk 的占位符值更改时使 bundle 的缓存失效。

默认情况下,使用 [id].js 或从 output.filename 推断出的值([name] 被替换为 [id] 或在前面加上 [id].)。

rspack.config.js
module.exports = {
  //...
  output: {
    //...
    chunkFilename: '[id].js',
  },
};

使用函数:

rspack.config.js
module.exports = {
  //...
  output: {
    chunkFilename: pathData => {
      return pathData.chunk.name === 'main' ? '[name].js' : '[name]/[name].js';
    },
  },
};

output.chunkFormat

  • 类型: false | 'array-push' | 'commonjs' | 'module' | string
  • 默认值: 根据 targetoutput.module 的配置推断

chunk 产物的格式,一般来说,target 为 web 或 webworker'时会使用 'array-push' 格式;为 ESM 时会使用 'module' 格式;为 node.js 时会使用 'commonjs' 格式,插件可能会添加其他格式。

TIP

这个选项的默认值取决于 targetoutput.module 设置。要了解更多详情,请在 Rspack 默认设置中搜索 "chunkFormat"

rspack.config.js
module.exports = {
  output: {
    chunkFormat: 'commonjs',
  },
};

output.chunkLoadTimeout

  • 类型: number
  • 默认值: 120000

Chunk 加载的超时时间(毫秒)。

rspack.config.js
module.exports = {
  //...
  output: {
    //...
    chunkLoadTimeout: 30000, // Chunk 加载会在 30 秒后超时
  },
};

output.chunkLoadingGlobal

此选项决定了 Rspack 用于加载 chunk 的全局变量。

rspack.config.js
module.exports = {
  output: {
    chunkLoadingGlobal: 'myCustomFunc',
  },
};

output.chunkLoading

  • 类型: false | 'jsonp' | 'import-scripts' | 'require' | 'async-node' | 'import'

加载 chunk 的方式,默认值会根据 targetchunkFormat 的配置而决定,一般来说,target 为 web 时会使用 'jsonp' 来加载 chunk;为 ESM 时会使用 'import' 来加载 chunk;为 webworker 时会使用 'import-scripts' 来加载 chunk;为 node.js 时会使用 'require' 来加载 chunk;为 async node.js 时会使用 'async-node'fs.readFile + vm.runInThisContext)来加载 chunk,插件可能会添加其他格式。

TIP

这个选项的默认值取决于 targetoutput.chunkFormat 设置。要了解更多详情,请在 Rspack 默认设置中搜索 "chunkLoading"

rspack.config.js
module.exports = {
  output: {
    chunkLoading: 'async-node',
  },
};

output.clean

  • 类型: boolean
  • 默认值: false

在生成产物前,删除输出目录下的所有文件。

rspack.config.js
module.exports = {
  //...
  output: {
    clean: true, // Clean the output directory before emit.
  },
};

output.crossOriginLoading

  • 类型: false | 'anonymous' | 'use-credentials'
  • 默认值: false

通过 crossOriginLoading 配置项,你可以为动态加载的 chunks 设置 crossorigin 属性

target'web' 时,Rspack 会动态创建 <script><link> 标签来加载异步的 JavaScript 和 CSS 资源。如果这些资源的 URL 在其他域名下,且 crossOriginLoading 不为 false,那么 Rspack 会为 <script><link> 标签添加 crossorigin 属性。

可选值

crossOriginLoading 有以下可选值:

  • false: 不设置 crossorigin 属性
  • 'anonymous':将 crossorigin 设置为 'anonymous',不包含用户凭据来跨域加载资源。
  • 'use-credentials':将 crossorigin 设置为 'use-credentials',包含用户凭据来跨域加载资源。

示例

比如将 output.publicPath 设置为 https://example.com/,并将 output.crossOriginLoading 设置为 'anonymous'

rspack.config.js
const path = require('path');

module.exports = {
  output: {
    publicPath: 'https://example.com/',
    crossOriginLoading: 'anonymous',
  },
};

当 Rspack 在加载异步的 JavaScript 资源时,会生成如下的 HTML:

<script src="https://example.com/foo.js" crossorigin="anonymous"></script>

output.cssChunkFilename

此选项决定了非初始(non-initial)CSS chunk 文件的名称,参阅 output.filename,了解可能的值。

在这里不能指定绝对路径。不过,可以随意包括用 '/' 分隔的文件夹。这个指定的路径将与 output.path 值结合,以精确定位磁盘上的位置。

output.cssFilename

  • 类型: string | (pathData: PathData, assetInfo?: JsAssetInfo) => string
  • 默认值: 根据 output.filename 推断

此选项决定了 CSS 文件的名称,参阅 output.filename,了解可能的值。

在这里不能指定绝对路径。不过,可以随意包括用 '/' 分隔的文件夹。这个指定的路径将与 output.path 值结合,以精确定位磁盘上的位置。

output.devtoolFallbackModuleFilenameTemplate

  • 类型: string | function (info)
  • 默认值: undefined

当模板字符串或函数产生重复时使用的备用内容。

详见 output.devtoolModuleFilenameTemplate.

output.devtoolModuleFilenameTemplate

  • 类型: string = 'webpack://[namespace]/[resource-path]?[loaders]' | function (info) => string
  • 默认值: undefined

此选项仅在 devtool 使用了需要模块名称的选项时使用。

自定义每个 source map 的 sources 数组中使用的名称。可以通过传递模板字符串或者函数来完成。例如,当使用 devtool: 'eval',默认值是:

rspack.config.js
module.exports = {
  //...
  output: {
    devtoolModuleFilenameTemplate:
      'webpack://[namespace]/[resource-path]?[loaders]',
  },
};

模板字符串支持以下模式:

模板 描述
[absolute-resource-path] 绝对路径文件名
[all-loaders] 自动和显式的 loader,并且参数取决于第一个 loader 名称
[hash] 模块标识符的 hash
[id] 模块标识符
[loaders] 显式的 loader,并且参数取决于第一个 loader 名称
[resource] 用于解析文件的路径和用于第一个 loader 的任意查询参数
[resource-path] 不带任何查询参数,用于解析文件的路径
[namespace] 模块命名空间。在构建成为一个 library 之后,通常也是 library 名称,否则为空

当使用一个函数,同样的选项要通过 info 参数并使用驼峰式:

rspack.config.js
module.exports = {
  //...
  output: {
    devtoolModuleFilenameTemplate: info => {
      return `webpack:///${info.resourcePath}?${info.loaders}`;
    },
  },
};

如果多个模块产生相同的名称,使用 output.devtoolFallbackModuleFilenameTemplate 来代替这些模块。

output.devtoolNamespace

  • 类型: string
  • 默认值: undefined

此选项确定 output.devtoolModuleFilenameTemplate 使用的模块名称空间。未指定时的默认值为:output.uniqueName。在加载多个通过 Rspack 构建的 library 时,用于防止 source map 中源文件路径冲突。

例如,如果你有两个 library,分别使用命名空间 library1library2,并且都有一个文件 ./src/index.js(可能具有不同内容),它们会将这些文件暴露为 webpack://library1/./src/index.jswebpack://library2/./src/index.js

output.enabledChunkLoadingTypes

启用用于入口 chunk 加载类型的列表。将由 Rspack 自动填充,仅在使用函数作为入口选项并从那里返回 chunkLoading 选项时需要。

rspack.config.js
module.exports = {
  //...
  output: {
    enabledChunkLoadingTypes: ['jsonp', 'require'],
  },
};

output.enabledLibraryTypes

入口点可用的 library 类型列表。

rspack.config.js
module.exports = {
  //...
  output: {
    enabledLibraryTypes: ['module'],
  },
};

output.enabledWasmLoadingTypes

开启可用的 Wasm 加载类型的运行时模块打包。

rspack.config.js
module.exports = {
  //...
  output: {
    enabledWasmLoadingTypes: ['fetch'],
  },
};

output.environment

指示 Rspack 可以在生成的运行时代码中使用哪种 ES 特性。

rspack.config.js
module.exports = {
  output: {
    environment: {
      // The environment supports arrow functions ('() => { ... }').
      arrowFunction: true,
      // The environment supports async function and await ('async function () { await ... }').
      asyncFunction: true,
      // The environment supports BigInt as literal (123n).
      bigIntLiteral: false,
      // The environment supports const and let for variable declarations.
      const: true,
      // The environment supports destructuring ('{ a, b } = obj').
      destructuring: true,
      // The environment supports an async import() function to import EcmaScript modules.
      dynamicImport: false,
      // The environment supports an async import() when creating a worker, only for web targets at the moment.
      dynamicImportInWorker: false,
      // The environment supports 'for of' iteration ('for (const x of array) { ... }').
      forOf: true,
      // The environment supports 'globalThis'.
      globalThis: true,
      // The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').
      module: false,
      // Determines if the node: prefix is generated for core module imports in environments that support it.
      // This is only applicable to Webpack runtime code.
      nodePrefixForCoreModules: false,
      // The environment supports optional chaining ('obj?.a' or 'obj?.()').
      optionalChaining: true,
      // The environment supports template literals.
      templateLiteral: true,
    },
  },
};

output.filename

  • 类型: string | (pathData: PathData, assetInfo?: JsAssetInfo) => string
  • 默认值: output.moduletrue 时为 '[name].mjs',否则为 '[name].js'

这个选项决定了输出的 JavaScript bundle 文件名称。这些 bundle 将会被写入 output.path 指定的目录下。

对于单个 Entry 来说,你可以使用一个固定名称,如:

rspack.config.js
module.exports = {
  output: {
    filename: 'bundle.js',
  },
};

然而,当通过多个 Entry、代码拆分或各种插件创建多个包时,您应该使用以下替换之一来给每个包一个唯一的名字...

对于拆分成多个 bundle 的情况的描述

Rspack 会对用户输入的代码进行代码拆分优化,这些优化可能包括但不限于:code splitting、bundle splitting,或通过其他插件实现的代码拆分等。 这些代码拆分的行为会导致生成多个 bundle,因此 bundle 的文件名需要动态生成。

使用 Entry 名称:

rspack.config.js
module.exports = {
  //...
  output: {
    filename: '[name].bundle.js',
  },
};

使用内部 chunk id:

rspack.config.js
module.exports = {
  //...
  output: {
    filename: '[id].bundle.js',
  },
};

使用从生成内容中生成的哈希值:

rspack.config.js
module.exports = {
  //...
  output: {
    filename: '[contenthash].bundle.js',
  },
};

将多个替换组合起来:

rspack.config.js
module.exports = {
  //...
  output: {
    filename: '[name].[contenthash].bundle.js',
  },
};

使用函数返回文件名:

rspack.config.js
module.exports = {
  //...
  output: {
    filename: pathData => {
      return pathData.chunk.name === 'main' ? '[name].js' : '[name]/[name].js';
    },
  },
};

这个选项被称为文件名,但你仍然可以使用类似 js/[name]/bundle.js 的东西来创建文件夹结构。

请注意,此选项不会影响到按需加载块的输出文件。它只影响最初加载的输出文件。对于按需加载的块文件,使用的是 output.chunkFilename 选项。由加载器创建的文件也不会受到影响。在这种情况下,您可能需要尝试特定加载器提供的可用选项。

Template String

可以用下方的模板字符串来替换对应文件名。不同的 context 对应了不同的可替换内容,如 output.assetModuleFilename 支持使用 file contextmodule context

Compilation Context

可在 compilation 层面替换的内容

模板 描述
[fullhash] compilation 的完整 hash

Chunk Context

可在 chunk 层面替换的内容:

模板 描述
[id] 当前 chunk id
[name] 当 chunk name 存在则使用名称,否则使用 chunk id
[chunkhash] chunk 的 hash 值,通过当前 chunk 中所有类型的元素计算所得
[contenthash] chunk 的 hash 值,通过只包含该类型内容的元素计算所得。如:生成 JavaScript 类型的文件则只会使用当前 chunk 中所有 JavaScript 模块计算所得的 hash

Module Context

可在 module 层面替换的内容:

模板 描述
[id] 模块的 id
[hash] 模块的 hash
[contenthash] 模块内容的 hash

File Context

可在 file 层面替换的内容:

模板 描述
[file] 文件名和路径,不包括查询或片段
[query] 文件 query,包含 ?
[fragment] # 开头的片段名
[base] 只翻译文件名(包括扩展名),不包括路径名
[path] 文件路径,不包含文件名
[name] 文件名,不包含扩展名和文件路径
[ext] 扩展名,包含 . (仅支持在 output.assetModuleFilename 里使用)

在 URL 级别上可用的替换:

模板 描述
[url] URL
TIP

[file] 等于 [path][base][base] 等于 [name][ext]。完整路径是 [path][name][ext][query][fragment][path][base][query][fragment][file][query][fragment]

Hash 的长度([hash][contenthash][chunkhash])可以使用 [hash:16] 来指定(默认为 20)。另外,可以使用 output.hashDigestLength 来全局配置长度。

当你想在实际文件名中使用占位符时,可以过滤掉占位符替换。例如,要输出一个文件 [name].js,你必须通过在括号之间添加反斜杠来转义 [name] 占位符。这样 [\name\] 会生成 [name] 而不是被替换为资源的名称。

示例:[\id\] 会生成 [id] 而不是被替换为 id。

如果使用函数来设置这个选项,函数将会接收一个包含上表中替换数据的对象。替换也会应用到返回的字符串中。传递的对象将具有这种类型:(属性取决于上下文)

type PathData = {
  hash: string;
  hashWithLength: (number) => string;
  chunk: Chunk | ChunkPathData;
  module: Module | ModulePathData;
  contentHashType: string;
  contentHash: string;
  contentHashWithLength: (number) => string;
  filename: string;
  url: string;
  runtime: string | SortableSet<string>;
  chunkGraph: ChunkGraph;
};
type ChunkPathData = {
  id: string | number;
  name: string;
  hash: string;
  hashWithLength: (number) => string;
  contentHash: Record<string, string>;
  contentHashWithLength: Record<string, (number) => string>;
};
type ModulePathData = {
  id: string | number;
  hash: string;
  hashWithLength: (number) => string;
};

output.globalObject

  • 类型: string
  • 默认值: 'self'

当输出为 library 时,尤其是当 libraryTarget'umd'时,此选项将决定使用哪个全局对象来挂载 library。为了使 UMD 构建在浏览器和 Node.js 上均可用,应将 output.globalObject 选项设置为 'this'。对于类似 web 的目标,默认为 self

入口点的返回值将会使用 output.library.name 赋值给全局对象。依赖于 target 配置项,全局对象将会发生对应的改变,例如:self, global 或者 globalThis

示例:

rspack.config.js
module.exports = {
  // ...
  output: {
    library: 'myLib',
    libraryTarget: 'umd',
    filename: 'myLib.js',
    globalObject: 'this',
  },
};

output.hashDigest

  • 类型: string
  • 默认值: 'hex'

在生成哈希时使用的编码方式。使用 'base64' 作为文件名可能会有问题,因为其中包含 / 字符。同样 'latin1' 也可能包含任何字符。

output.hashDigestLength

  • 类型: number
  • 默认值: 20

要使用的哈希摘要的长度。

TIP

hashDigestLength 默认值为 20,当启用 experiments.futureDefaults 时将使用 16 作为默认值。

output.hashFunction

  • 类型: 'md4' | 'xxhash64'
  • 默认值: 'md4'

要使用的哈希算法。

rspack.config.js
module.exports = {
  //...
  output: {
    hashFunction: 'xxhash64',
  },
};
TIP

hashFunction 支持更快的 xxhash64 算法,当启用 experiments.futureDefaults 时将使用它作为默认值。

output.hashSalt

  • 类型: string
  • 默认值: undefined

可选的 salt,用于更新哈希值。

output.hotUpdateChunkFilename

  • 类型: string
  • 默认值: "[id].[fullhash].hot-update.js"

自定义热更新文件的文件名,参阅 output.filename,了解可能的值。只有 [fullhash][id] 可用作占位符。

rspack.config.js
module.exports = {
  //...
  output: {
    hotUpdateChunkFilename: '[id].[fullhash].hot-update.js',
  },
};
TIP

通常你不需要更改 output.hotUpdateChunkFilename

output.hotUpdateGlobal

  • 类型: string
  • 默认值: "webpackHotUpdate" + output.uniqueName

仅当 target 设置为 "web" 时使用,它使用 JSONP 来加载热更新。

JSONP 函数用于异步加载热更新块。

具体可以参阅 output.chunkLoadingGlobal

output.hotUpdateMainFilename

  • 类型: string
  • 默认值: "[runtime].[fullhash].hot-update.json"

自定义热更新清单文件的文件名。只有 [fullhash][runtime] 可用作占位符。

TIP

通常你不需要更改 output.hotUpdateMainFilename

output.iife

  • 类型: boolean
  • 默认值: true

让 Rspack 为生成的代码添加 IIFE 包装器。

rspack.config.js
module.exports = {
  //...
  output: {
    iife: true,
  },
};

output.importFunctionName

  • 类型: string
  • 默认值: 'import'

内部 import() 函数的名称. 可用于 polyfilling,例如通过 dynamic-import-polyfill.

rspack.config.js
module.exports = {
  //...
  output: {
    importFunctionName: '__import__',
  },
};

output.library

输出一个库,为你的入口做导出。

  • 类型: string | string[] | object

一起来看一个简单的示例。

rspack.config.js
module.exports = {
  // …
  entry: './src/index.js',
  output: {
    library: 'MyLibrary',
  },
};

假设你在 src/index.js 的入口中导出了如下函数:

export function hello(name) {
  console.log(`hello ${name}`);
}

此时,变量 MyLibrary 将与你的入口文件所导出的文件进行绑定,下面是如何使用 Rspack 构建的库的实现:

<script src="https://example.org/path/to/my-library.js"></script>
<script>
  MyLibrary.hello('rspack');
</script>

在上面的例子中,我们为 entry 设置了一个入口文件,然而 Rspack 可以接受 多个入口,例如一个 array 或者一个 object

  1. 如果你将 entry 设置为一个 array,那么只有数组中的最后一个会被暴露。

    module.exports = {
      // …
      entry: ['./src/a.js', './src/b.js'], // 只有在 b.js 中导出的内容才会被暴露
      output: {
        library: 'MyLibrary',
      },
    };
  2. 如果你将 entry 设置为一个 object,所以入口都可以通过 libraryarray 语法暴露:

    module.exports = {
      // …
      entry: {
        a: './src/a.js',
        b: './src/b.js',
      },
      output: {
        filename: '[name].js',
        library: ['MyLibrary', '[name]'], // name is a placeholder here
      },
    };

    假设 a.jsb.js 导出名为 hello 的函数,这就是如何使用这些库的方法:

    <script src="https://example.org/path/to/a.js"></script>
    <script src="https://example.org/path/to/b.js"></script>
    <script>
      MyLibrary.a.hello('rspack');
      MyLibrary.b.hello('rspack');
    </script>

output.library.amdContainer

  • 类型: string

在全局为 AMD 模块添加 define/require 函数的容器。

WARNING

请注意,amdContainer 的值必须设置为全局变量。

rspack.config.js
module.exports = {
  // …
  output: {
    library: {
      amdContainer: 'window["clientContainer"]',
      type: 'amd', // or 'amd-require'
    },
  },
};

这将产生以下 bundle:

window['clientContainer'].define(/*define args*/); // or 'amd-require' window['clientContainer'].require(/*require args*/);

output.library.name

指定库的名称。

  • 类型:string | string[] | {amd?: string, commonjs?: string, root?: string | string[]}
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
    },
  },
};

output.library.type

配置将库暴露的方式。

  • 类型: string

    类型默认包括 'var''module''assign''assign-properties''this''window''self''global''commonjs''commonjs2''commonjs-module''commonjs-static''amd''amd-require''umd''umd2''jsonp''system',除此之外也可以通过插件添加。

对于接下来的示例,我们将会使用 _entry_return_ 表示被入口点返回的值。

暴露一个变量

这些选项将入口点的返回值(例如,入口点导出的内容)分配给 output.library.name 中配置的名称,无论 bundle 被包含在什么作用域中。

type: 'var'
rspack.config.js
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'var',
    },
  },
};

让你的库加载之后,入口起点的返回值 将会被赋值给一个变量:

var MyLibrary = _entry_return_;

// 在加载了 `MyLibrary` 的单独脚本中
MyLibrary.doSomething();
type: 'assign'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'assign',
    },
  },
};

这将生成一个隐含的全局变量,它有可能重新分配一个现有的值(请谨慎使用):

MyLibrary = _entry_return_;

请注意,如果 MyLibrary 没有在你的库之前定义,那么它将会被设置在全局作用域。

type: 'assign-properties'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'assign-properties',
    },
  },
};

type: 'assign' 相似但是更安全,因为如果 MyLibrary 已经存在的话,它将被重用:

// 仅在当其不存在是创建 MyLibrary
MyLibrary = typeof MyLibrary === 'undefined' ? {} : MyLibrary;
// 然后复制返回值到 MyLibrary
// 与 Object.assign 行为类似

// 例如,你像下面这样在你的入口导出一个 `hello` 函数
export function hello(name) {
  console.log(`Hello ${name}`);
}

// 在另外一个已经加载 MyLibrary 的脚本中
// 你可以像这样运行 `hello` 函数
MyLibrary.hello('World');

通过对象赋值暴露

这些配置项分配入口点的返回值(例如:无论入口点导出的什么内容)到一个名为 output.library.name 的对象中。

type: 'this'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'this',
    },
  },
};

入口起点的返回值 将会被赋值给 this 对象下的 output.library.name 属性。this 的含义取决于你:

this['MyLibrary'] = _entry_return_;

// 在一个单独的脚本中
this.MyLibrary.doSomething();
MyLibrary.doSomething(); // 如果 `this` 为 window 对象
type: 'window'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'window',
    },
  },
};

入口起点的返回值 将会被赋值给 window 对象下的 output.library.name

window['MyLibrary'] = _entry_return_;

window.MyLibrary.doSomething();
type: 'global'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'global',
    },
  },
};

入口起点的返回值 将会被复制给全局对象下的 output.library.name。取决于 target 值,全局对象可以分别改变,例如,selfglobal 或者 globalThis

global['MyLibrary'] = _entry_return_;

global.MyLibrary.doSomething();
type: 'commonjs'
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'commonjs',
    },
  },
};

入口起点的返回值 将使用 output.library.name 赋值给 exports 对象。顾名思义,这是在 CommonJS 环境中使用。

exports['MyLibrary'] = _entry_return_;

require('MyLibrary').doSomething();
WARNING

注意,不设置 output.library.name 将导致入口起点返回的所有属性都被赋值给给定的对象;不检查现有的属性名。

模块定义系统

这些配置项将生成一个带有完整 header 的 bundle,以确保与各种模块系统兼容。output.library.name 配置项在不同的 output.library.type 中有不同的含义。

type: 'module'
rspack.config.js
module.exports = {
  // …
  experiments: {
    outputModule: true,
  },
  output: {
    library: {
      // do not specify a `name` here
      type: 'module',
    },
  },
};

输出 ESM 模块。

但这个特性仍然是实验性的,还没有完全支持,所以在使用之前确保启用了 experiments.outputModule。此外,你可以在这个 issue 中跟踪开发进度。

type: 'commonjs2'
module.exports = {
  // …
  output: {
    library: {
      // note there's no `name` here
      type: 'commonjs2',
    },
  },
};

入口起点的返回值 将会被赋值给 module.exports。顾名思义,这是在 Node.js(CommonJS)环境中使用的:

module.exports = _entry_return_;

require('MyLibrary').doSomething();

如果我们指定 output.library.nametype: commmonjs2,你的入口起点的返回值将会被赋值给 module.exports.[output.library.name]

TIP

在考虑 CommonJS 与 CommonJS2 之间的区别?虽然它们很相似,但是它们之间有一些细微的差别,这些差别在 Rspack 的上下文中通常是不相关的。(要获取更多详细内容,请 阅读这个 issue。)

type: 'commonjs-static'
module.exports = {
  // …
  output: {
    library: {
      // note there's no `name` here
      type: 'commonjs-static',
    },
  },
};

单个导出将被设置为 module.exports 中的属性。名称中的“static”是指输出是静态可分析的,因此具名导出可以通过 Node.js 导入到 ESM 中:

输入:

export function doSomething() {}

输出:

function doSomething() {}

// …

exports.doSomething = __webpack_exports__.doSomething;

消费(CommonJS):

const { doSomething } = require('./output.cjs'); // doSomething => [Function: doSomething]

消费(ESM):

import { doSomething } from './output.cjs'; // doSomething => [Function: doSomething]
TIP

当源代码是用 ESM 编写的,并且输出应该兼容 CJS 和 ESM 时,这是很有用的。获取更多详情,请阅读该 issue 或者 这篇文档(尤其是 这个章节)。

type: 'amd'

这将使库作为一个 AMD 模块暴露出来。

AMD 模块要求入口 chunk(例如,通过 <script> 标签加载的第一个脚本)具有特定属性,例如 definerequire,这些通常由 RequireJS 或任何兼容的加载器(如 almond)提供。否则,直接加载生成的 AMD 包将导致错误,例如 define is not defined

配置如下配置:

rspack.config.js
module.exports = {
  //...
  output: {
    library: {
      name: 'MyLibrary',
      type: 'amd',
    },
  },
};

生成的输出将被定义为名为 "MyLibrary",比如:

define('MyLibrary', [], function () {
  return _entry_return_;
});

包可以作为脚本标签的一部分被包含,并且可以像这样调用:

require(['MyLibrary'], function (MyLibrary) {
  // Do something with the library...
});

如果 output.library.name 未定义,则生成以下内容。

define(function () {
  return _entry_return_;
});

直接使用 <script> 标签加载这个包将无法按预期工作,或者根本无法工作(在使用 almond 加载器的情况下)。它只能通过 RequireJS 兼容的异步模块加载器并通过该文件的实际路径来工作。因此,在这种情况下,如果这些文件直接暴露在服务器上,output.pathoutput.filename 可能会变得非常重要。

type: 'amd-require'
rspack.config.js
module.exports = {
  //...
  output: {
    library: {
      name: 'MyLibrary',
      type: 'amd-require',
    },
  },
};

这会将你的输出打包成一个立即执行的 AMD require(dependencies, factory) 包装器。

amd-require 类型允许使用 AMD 依赖项,而不需要后续的单独调用。与 amd 类型一样,这取决于在加载 Rspack 输出的环境中是否有适当的 require 函数可用。

使用这种类型时,库名称不能被使用。

type: 'umd'

这将在所有模块定义下暴露你的库, 允许它与 CommonJS、AMD 和作为全局变量工作。可以查看 UMD Repository 获取更多内容。

在这种情况下,你需要使用 library.name 属性命名你的模块:

module.exports = {
  //...
  output: {
    library: {
      name: 'MyLibrary',
      type: 'umd',
    },
  },
};

最终的输出为:

(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if (typeof define === 'function' && define.amd) define([], factory);
  else if (typeof exports === 'object') exports['MyLibrary'] = factory();
  else root['MyLibrary'] = factory();
})(global, function () {
  return _entry_return_;
});

请注意,根据对象赋值部分,省略 library.name 将导致入口起点返回的所有属性直接赋值给根对象。示例:

module.exports = {
  //...
  output: {
    libraryTarget: 'umd',
  },
};

输出将会是:

(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if (typeof define === 'function' && define.amd) define([], factory);
  else {
    var a = factory();
    for (var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  }
})(global, function () {
  return _entry_return_;
});

你可以为 library.name 指定一个对象,每个目标的名称不同:

module.exports = {
  //...
  output: {
    library: {
      name: {
        root: 'MyLibrary',
        amd: 'my-library',
        commonjs: 'my-common-library',
      },
      type: 'umd',
    },
  },
};
type: 'system'

这将会把你的库暴露为一个 System.register 模块。

System 模块要求当 bundle 执行时,全局变量 System 出现在浏览器中。编译的 System.register 格式允许你在没有额外配置的情况下使用 System.import('/bundle.js'),并将你的 bundle 加载到系统模块注册表中。

module.exports = {
  //...
  output: {
    library: {
      type: 'system',
    },
  },
};

输出:

System.register([], function (__WEBPACK_DYNAMIC_EXPORT__, __system_context__) {
  return {
    execute: function () {
      // ...
    },
  };
});

除了设置 output.library.typesystem,还要将 output.library.name 添加到配置中,输出的 bundle 将以库名作为 System.register 的参数:

System.register(
  'MyLibrary',
  [],
  function (__WEBPACK_DYNAMIC_EXPORT__, __system_context__) {
    return {
      execute: function () {
        // ...
      },
    };
  },
);

其他类型

type: 'jsonp'

rspack.config.js
module.exports = {
  // …
  output: {
    library: {
      name: 'MyLibrary',
      type: 'jsonp',
    },
  },
};

这将把您的入口返回值包装在一个 JSONP 中。

MyLibrary(_entry_return_);

库的依赖项将由 externals 配置定义。

output.library.export

指定哪一个导出应该被暴露为一个库。

  • 类型: string | string[]
  • 默认值: undefined

默认情况下为 undefined,将导出整个(命名空间)对象。下述 demo 演示了使用 output.library.type: 'var' 配置型产生的作用。

rspack.config.js
module.exports = {
  output: {
    library: {
      name: 'MyLibrary',
      type: 'var',
      export: 'default',
    },
  },
};

入口点的默认导出将会被赋值为库名称:

// 如果你的库有默认导出
var MyLibrary = _entry_return_.default;

你可以传递一个数组给 output.library.export,它将被解析为要分配给库名称的模块路径:

rspack.config.js
module.exports = {
  output: {
    library: {
      name: 'MyLibrary',
      type: 'var',
      export: ['default', 'subModule'],
    },
  },
};

这里是库代码:

var MyLibrary = _entry_return_.default.subModule;

output.library.auxiliaryComment

在 UMD 包装器中添加注释。

  • 类型: string | { amd?: string, commonjs?: string, commonjs2?: string, root?: string }
  • 默认值: undefined

为每个 umd 类型插入相同的注释,将 auxiliaryComment 设置为 string。

module.exports = {
  // …
  mode: 'development',
  output: {
    library: {
      name: 'MyLibrary',
      type: 'umd',
      auxiliaryComment: 'Test Comment',
    },
  },
};

这将产生以下结果:

(function webpackUniversalModuleDefinition(root, factory) {
  //Test Comment
  if (typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  //Test Comment
  else if (typeof define === 'function' && define.amd) define([], factory);
  //Test Comment
  else if (typeof exports === 'object') exports['MyLibrary'] = factory();
  //Test Comment
  else root['MyLibrary'] = factory();
})(self, function () {
  return _entry_return_;
});

对于细粒度控制,可以传递一个对象:

module.exports = {
  // …
  mode: 'development',
  output: {
    library: {
      name: 'MyLibrary',
      type: 'umd',
      auxiliaryComment: {
        root: 'Root Comment',
        commonjs: 'CommonJS Comment',
        commonjs2: 'CommonJS2 Comment',
        amd: 'AMD Comment',
      },
    },
  },
};

output.library.umdNamedDefine

  • 类型: boolean
  • 默认值: undefined

当使用 output.library.type: "umd" 时,将 output.library.umdNamedDefine 设置为 true 将会把 AMD 模块命名为 UMD 构建。否则使用匿名 define

module.exports = {
  //...
  output: {
    library: {
      name: 'MyLibrary',
      type: 'umd',
      umdNamedDefine: true,
    },
  },
};

AMD module 将会是这样:

define('MyLibrary', [], factory);

output.module

Stability: Experimental
  • 类型: boolean
  • 默认值: false

以 ESM 模块的形式输出 JavaScript 文件。由于此功能还处于实验阶段,默认关闭,想要使用的话必须将 experiments.outputModule 设置为 true。

当启用时,Rspack 会将 output.iife 设置为 falseoutput.scriptType 设置为 'module'

如果你正在使用 Rspack 编译一个供他人使用的库,请确保在 output.moduletrue 时将 output.library.type 设置为 'module'

rspack.config.js
module.exports = {
  //...
  experiments: {
    outputModule: true,
  },
  output: {
    module: true,
  },
};

output.path

  • 类型: string
  • 默认值: path.resolve(process.cwd(), 'dist')

输出文件目录的绝对路径。

rspack.config.js
const path = require('path');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist/assets'),
  },
};

注意 [fullhash] 将会被替换为构建过程中的 hash 值。

WARNING

路径中不能包含感叹号(!),因为感叹号在 Rspack 中被用作 loader 语法。

output.pathinfo

  • 类型: boolean | 'verbose'
  • 默认值: true

让 Rspack 在 bundle 中通过注释输出模块的信息。此选项在 mode'development' 下默认为 true,为 'production' 下默认为 false'verbose' 会打印更多信息,例如模块导出、运行时信息和 bailout 原因。

WARNING

在开发过程中分析生成的代码时,这些注释提供的信息很有用,但不应在生产环境中使用。

rspack.config.js
module.exports = {
  //...
  output: {
    pathinfo: true,
  },
};
TIP

它还在生成的 bundle 中添加了一些关于 tree shaking 的信息。

output.publicPath

  • 类型: 'auto' | string | ((pathData: PathData, assetInfo?: JsAssetInfo) => string)
  • 默认值: targets 为 'web''webworker' 时为 'auto'

此选项决定了引用的资源的 URL 前缀,如: 图片、文件等等。

例如,给定一个配置文件:

rspack.config.js
module.exports = {
  output: {
    publicPath: '/assets/',
    chunkFilename: '[id].chunk.js',
    assetModuleFilename: '[name][ext]',
  },
};

对于某一个非初始(non-initial) chunk 文件,它的请求 URL 看起来像是这样: /assets/1.chunk.js

对于一个图片的引用,它的请求 URL 看起来像是这样:/assets/logo.png

同时,当你使用 CDN 对产物进行部署时则非常有用:

rspack.config.js
module.exports = {
  output: {
    publicPath: 'https://cdn.example.com/assets/',
    assetModuleFilename: '[name][ext]',
  },
};

对于所有 asset 资源,它们的请求 URL 看起来像是这样:https://cdn.example.com/assets/logo.png

动态设置 publicPath

在运行时代码中,你可以通过 __webpack_public_path__ 来动态设置 publicPath__webpack_public_path__ 会覆盖 Rspack 配置中的 publicPath,但只能对异步加载的资源生效。

首先创建一个 publicPath.js

publicPath.js
__webpack_public_path__ = 'https://cdn.example.com/assets/';

然后在入口文件的第一行引入它即可:

entry.js
import './publicPath.js';
import './others.js';

output.scriptType

  • 类型: 'module' | 'text/javascript' | boolean
  • 默认值: false

该选项允许使用自定义脚本类型(例如 <script type="module" ...>)来加载异步块。

TIP

如果 output.module 设置为 true,则 output.scriptType 将默认为 'module' 而不是 false

rspack.config.js
module.exports = {
  //...
  output: {
    scriptType: 'module',
  },
};

output.sourceMapFilename

  • 类型: string
  • 默认值: '[file].map[query]'

配置 source map 文件的命名方式。仅当 devtool 设置为 'source-map' 时生效,此时会输出文件。

可以使用 output.filename 中的 [name][id][fullhash][chunkhash] 替换符。此外,还可以使用 Template strings 中在文件级别列出的替换符。

output.strictModuleErrorHandling

  • 类型: boolean
  • 默认值: false

按照 ES Module 规范处理 module 加载时的错误,会有性能损失。

rspack.config.js
module.exports = {
  //...
  output: {
    strictModuleErrorHandling: true,
  },
};

output.trustedTypes

  • 类型: true | string | object
  • 默认值: undefined

控制 Trusted Types 兼容性。启用此选项,Rspack 将检测已实现了 Trusted Types,并使用 Trusted Types 来创建它动态加载的脚本 URL。应用在运行带有 require-trusted-types-for 内容安全策略指令下的应用程序。

默认情况下是不启用。

  • 当设置为 true 时,Rspack 将使用 output.uniqueName 作为 Trusted Types 策略名称。
  • 当设置为非空字符串时,其值将被用作策略名称。
  • 当设置为对象时,策略名称将从对象的 policyName 属性中获取。
rspack.config.js
module.exports = {
  //...
  output: {
    trustedTypes: {
      policyName: 'my-application#webpack',
    },
  },
};

output.uniqueName

  • 类型: string
  • 默认值: 默认使用 output.library 名称或者上下文中的 package.json 的 包名称(package name), 如果两者都不存在,值为 ''

此选项决定了在全局环境下为防止多个 Rspack 运行时 冲突所使用的唯一名称。

output.uniqueName 将用于生成唯一全局变量:

rspack.config.js
module.exports = {
  output: {
    uniqueName: 'my-package-xyz',
  },
};

output.wasmLoading

  • 类型: false | 'fetch', 'async-node'
  • 默认值: 'fetch'

用于设置加载 WebAssembly 模块的方式。默认方式包括 'fetch'(web/webworker)、'async-node'(Node.js)

默认值会受不同 target 的影响:

  • 如果目标设置为 'web''webworker''electron-renderer''node-webkit',默认值为 'fetch'
  • 如果目标设置为 'node''async-node''electron-main''electron-preload',则默认为 'async-node'
rspack.config.js
module.exports = {
  //...
  output: {
    wasmLoading: 'fetch',
  },
};

output.webassemblyModuleFilename

  • 类型: string
  • 默认值: '[hash].module.wasm'

指定 WebAssembly 模块的文件名。作为 output.path 目录下的相对路径。

rspack.config.js
module.exports = {
  //...
  output: {
    webassemblyModuleFilename: '[id].[hash].wasm',
  },
};

output.workerChunkLoading

  • 类型: false | 'jsonp' | 'import-scripts' | 'require' | 'async-node' | 'import'
  • 默认值: false

workerChunkLoading 控制 chunk 加载方式。

TIP

此选项的默认值取决于目标设置。要获取更多信息,请在 Rspack 默认设置中搜索 "workerChunkLoading"

rspack.config.js
module.exports = {
  //...
  output: {
    workerChunkLoading: false,
  },
};

output.workerPublicPath

  • 类型: string
  • 默认值: ""

为 Worker 设置一个公共路径,默认为 output.publicPath 的值。只有在 Worker 脚本位于与其他脚本不同的路径时才使用此选项。

rspack.config.js
module.exports = {
  //...
  output: {
    workerPublicPath: '/workerPublicPath2/',
  },
};

output.workerWasmLoading

  • 类型: false | 'fetch-streaming' | 'fetch' | 'async-node' | string
  • 默认值: false

用来设置在 Worker 中加载 WebAssembly 模块的方式,默认为 output.wasmLoading 的值。

rspack.config.js
module.exports = {
  //...
  output: {
    workerWasmLoading: 'fetch',
  },
};

output.auxiliaryComment

WARNING

output.libraryExport

WARNING

我们可能会停止对此的支持,所以最好使用 output.library.export,其作用与 libraryExport 一致。

output.libraryTarget

WARNING

请使用 output.library.type 代替,因为我们可能在未来放弃对 output.libraryTarget 的支持。

output.umdNamedDefine

WARNING