Output

本章节描述了 Rsbuild 中与构建产物有关的配置。

output.assetPrefix

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

在生产环境使用 CDN 部署时,可使用该选项设置静态资源的 URL 前缀。

assetPrefix 会影响构建产物中绝大部分静态资源的 URL,包括 JavaScript 文件、CSS 文件、图片、视频等。如果指定了一个错误的值,则在加载这些资源时可能会出现 404 错误。

该配置项仅用于生产环境。在开发环境下,请使用 dev.assetPrefix 配置项进行设置。

设置后,项目的 JavaScript、CSS、图片等静态资源的 URL 都会加上 output.assetPrefix 作为前缀:

示例

export default {
  output: {
    assetPrefix: 'https://cdn.example.com/assets/',
  },
};

构建之后,可以看到 JS 文件从以下地址加载:

<script
  defer
  src="https://cdn.example.com/assets/static/js/main.ebc4ff4f.js"
></script>

与原生配置的区别

output.assetPrefix 对应以下原生配置:

它与原生配置的区别在于:

  • output.assetPrefix 仅在生产环境下生效。
  • output.assetPrefix 默认会自动补全尾部的 /
  • output.assetPrefix 的值会写入 process.env.ASSET_PREFIX 环境变量。

output.charset

  • 类型: 'ascii' | 'utf8'
  • 默认值: 'ascii'

默认情况下,Rsbuild 的产物内容是纯 ASCII 的,并且会转义所有非 ASCII 字符。

如果你不希望对字符进行转义,而是输出所有原始字符,可以将 output.charset 设置为 utf8

export default {
  output: {
    charset: 'utf8',
  },
};

output.cleanDistPath

  • 类型: boolean
  • 默认值: true

是否在构建开始前清理 dist 目录下的所有文件。

默认情况下,Rsbuild 会自动清理 dist 目录下的文件,你可以把 cleanDistPath 设置为 false 来禁用该行为。

export default {
  output: {
    cleanDistPath: false,
  },
};

output.copy

  • 类型: CopyPluginOptions | CopyPluginOptions['patterns']
  • 默认值: undefined

将指定的文件或目录拷贝到构建输出目录中。

例如,将 src/assets 下的文件直接拷贝到 dist 目录:

export default {
  output: {
    copy: [{ from: './src/assets', to: '' }],
  },
};

更详细的配置项请参考:copy-webpack-plugin 文档。

output.cssModules

  • 类型:
type CssModules = {
  auto?: boolean | RegExp | ((resourcePath: string) => boolean);
  localIdentName?: string;
  exportLocalsConvention?: CssModuleLocalsConvention;
};

用于自定义 CSS Modules 配置。

cssModules.auto

auto 配置项允许基于文件名自动启用 CSS 模块。

  • 类型: boolean | RegExp | ((resourcePath: string) => boolean)
  • 默认值: true

类型说明:

  • true: 为所有匹配 /\.module\.\w+$/i.test(filename) 正则表达式的文件启用 CSS 模块。
  • false: 禁用 CSS 模块。
  • RegExp: 为所有匹配 /RegExp/i.test(filename) 正则表达式的文件禁用 CSS 模块。
  • function: 为所有通过基于文件名的过滤函数校验的文件启用 CSS 模块。
export default {
  output: {
    cssModules: {
      auto: (resource) => {
        return resource.includes('.module.') || resource.includes('shared/');
      },
    },
  },
};

cssModules.exportLocalsConvention

导出的类名称的样式。

  • 类型:
type CssModuleLocalsConvention =
  | 'asIs'
  | 'camelCase'
  | 'camelCaseOnly'
  | 'dashes'
  | 'dashesOnly';
  • 默认值: 'camelCase'

类型说明:

  • asIs 类名将按原样导出。
  • camelCase 类名将被驼峰化,原始类名仍然可用。
  • camelCaseOnly 类名将被驼峰化,原始类名不可用。
  • dashes 只有类名中的破折号会被驼峰化,原始类名仍然可用。
  • dashesOnly 只有类名中的破折号会被驼峰化,原始类名不可用。
export default {
  output: {
    cssModules: {
      exportLocalsConvention: 'camelCaseOnly',
    },
  },
};

cssModules.localIdentName

  • 类型: string
  • 默认值:
// isProd 表示生产环境构建
const localIdentName = isProd
  ? '[local]-[hash:base64:6]'
  : '[path][name]__[local]-[hash:base64:6]';

设置 CSS Modules 编译后生成的 className 格式。

默认值

localIdentName 在开发环境和生产环境有不同的默认值。

在生产环境,Rsbuild 会生成更简短的类名,从而减少构建产物的体积。

import styles from './index.module.scss';

// 在开发环境下,值为 `.src-index-module__header-xxxxxx`
// 在生产环境下,值为 `.header-xxxxxx`
console.log(styles.header);

模板字符串

localIdentName 中,你可以使用以下模板字符串:

  • [name] - 源文件名称。
  • [local] - 原始类名。
  • [hash] - 字符串的哈希值。
  • [folder] - 文件夹的相对路径。
  • [path] - 源文件的相对路径。
  • [file] - 文件名和路径。
  • [ext] - 文件后缀名,包含点号。
  • [hash:<hashDigest>:<hashDigestLength>] - 带有哈希设置的哈希。
TIP

在使用 Rspack 作为打包工具时, 暂不支持配置 <hashDigest>

示例

localIdentName 设置为其他值:

export default {
  output: {
    cssModules: {
      localIdentName: '[hash:base64:4]',
    },
  },
};

output.dataUriLimit

  • 类型:
type DataUriLimitConfig = {
  svg?: number;
  font?: number;
  image?: number;
  media?: number;
};
  • 默认值:
const defaultDatUriLimit = {
  svg: 10000,
  font: 10000,
  image: 10000,
  media: 10000,
};

设置图片、字体、媒体等静态资源被自动内联为 base64 的体积阈值。

默认情况下,体积小于 10KB 的图片、字体、媒体等文件,会自动经过 Base64 编码,内联到页面中,不再会发送独立的 HTTP 请求。

你可以通过修改 dataUriLimit 参数来调整这个阈值。

其中:

  • svg:表示 SVG 图片的体积阈值。
  • font:表示字体文件的体积阈值。
  • image:表示非 SVG 图片的体积阈值。
  • media:表示视频等媒体资源的体积阈值。

示例

修改图片资源的阈值为 5000 Bytes,设置视频资源不内联:

export default {
  output: {
    dataUriLimit: {
      image: 5000,
      media: 0,
    },
  },
};

output.disableCssExtract

  • 类型: boolean
  • 默认值: false

是否禁用 CSS 提取逻辑,并将 CSS 文件内联到 JS 文件中。

默认情况下,Rsbuild 会把 CSS 提取为独立的 .css 文件,并输出到构建产物目录。设置该选项为 true 后,CSS 文件会被内联到 JS 文件中,并在运行时通过 <style> 标签插入到页面上。

示例

export default {
  output: {
    disableCssExtract: true,
  },
};

注意事项

建议仅在开发环境在开启 disableCssExtract 选项。

对于生产环境构建,建议使用 Rsbuild 的默认行为,将 CSS 抽取为单独的 bundle,以便浏览器能够并行加载 CSS 和 JS 资源。

比如:

export default {
  output: {
    disableCssExtract: process.env.NODE_ENV === 'development',
  },
};

如果你需要在生产环境下开启该选项,请留意内联的 CSS 代码不会经过 Rsbuild 默认的 CSS 压缩器,你可以手动注册 PostCSS 的 cssnano 插件来对内联代码进行压缩。

  1. 安装 cssnano:
npm add cssnano -D
  1. 使用 tools.postcss 注册 cssnano:
export default {
  tools: {
    postcss: (opts) => {
      opts.postcssOptions.plugins.push(require('cssnano'));
    },
  },
};

output.distPath

  • 类型:
type DistPathConfig = {
  root?: string;
  html?: string;
  js?: string;
  css?: string;
  svg?: string;
  font?: string;
  wasm?: string;
  image?: string;
  media?: string;
  server?: string;
  worker?: string;
};
  • 默认值:
const defaultDistPath = {
  root: 'dist',
  html: '/',
  js: 'static/js',
  css: 'static/css',
  svg: 'static/svg',
  font: 'static/font',
  wasm: 'static/wasm',
  image: 'static/image',
  media: 'static/media',
  server: 'bundles',
  worker: 'worker',
};

设置构建产物的输出目录,Rsbuild 会根据产物的类型输出到对应的子目录下。

其中:

  • root: 表示所有构建产物输出的根目录。
  • html:表示 HTML 文件的输出目录。
  • js:表示 JavaScript 文件的输出目录。
  • css:表示 CSS 样式文件的输出目录。
  • svg:表示 SVG 图片的输出目录。
  • font:表示字体文件的输出目录。
  • wasm:表示 WebAssembly 文件的输出目录。
  • image:表示非 SVG 图片的输出目录。
  • media:表示视频等媒体资源的输出目录。
  • server: 表示服务端产物的输出目录,仅在 target 为 node 时有效。
  • worker: 表示 worker 产物的输出目录,仅在 target 为 service-worker 时有效。

根目录

root 是构建产物的根目录,可以为相对路径或绝对路径。如果 root 的值为相对路径,则会基于当前项目的根目录拼接为绝对路径。

其他目录只能为相对路径,并且会相对于 root 进行输出。

示例

以 JavaScript 文件为例,会输出到 distPath.root + distPath.js 目录,即为 dist/static/js

如果需要将 JavaScript 文件输出到 build/resource/js 目录,可以这样设置:

export default {
  output: {
    distPath: {
      root: 'build',
      js: 'resource/js',
    },
  },
};

output.disableMinimize

  • 类型: boolean
  • 默认值: false

是否禁用生产环境下的代码压缩。

默认情况下,JS 代码和 CSS 代码会在生产环境构建时被自动压缩,从而提升页面性能。如果你不希望执行代码压缩,可以将 disableMinimize 设置为 true

export default {
  output: {
    disableMinimize: true,
  },
};
TIP

该配置项通常用于代码调试和问题排查,不建议在生产环境禁用代码压缩,否则会导致页面性能显著下降。

output.disableSourceMap

  • 类型:
type DisableSourceMap =
  | boolean
  | {
      js?: boolean;
      css?: boolean;
    };
  • 默认值:
const defaultDisableSourceMap = {
  js: false,
  css: process.env.NODE_ENV === 'production',
};

是否禁用 Source Map 生成。

什么是 Source Map

Source Map 是保存源代码映射关系的信息文件,它记录了编译后的代码的每一个位置,以及所对应的编译前的位置。通过 Source Map,可以在调试编译后的代码时,直接查看对应的源代码。

默认情况下,Rsbuild 的 Source Map 生成规则如下:

  • 在开发环境构建时,会生成 JS 文件和 CSS 文件的 SourceMap,便于进行开发调试。
  • 在生产环境构建时,会生成 JS 文件的 Source Map,用于调试和排查线上问题;不会生成 CSS 文件的 Source Map。

如果项目不需要 Source Map,可以关闭该功能,从而提升构建的速度。

export default {
  output: {
    disableSourceMap: true,
  },
};

如果需要开启开发环境的 Source Map,并在生产环境禁用,可以设置为:

export default {
  output: {
    disableSourceMap: process.env.NODE_ENV === 'production',
  },
};

如果需要单独控制 JS 文件或 CSS 文件的 Source Map,可以参考下方设置:

export default {
  output: {
    disableSourceMap: {
      js: false,
      css: true,
    },
  },
};

output.disableFilenameHash

  • 类型: boolean
  • 默认值: false

移除生产环境的构建产物名称中的 hash 值。

在生产环境构建后,会自动在文件名中间添加 hash 值,如果不需要添加,可以通过 output.disableFilenameHash 配置来禁用该行为。

示例

默认情况下,构建后的产物名称为:

File                                     Size         Gzipped
dist/static/css/187.7879e19d.css         126.99 KB    9.17 KB
dist/static/js/main.18a568e5.js          2.24 KB      922 B

添加 output.disableFilenameHash 配置:

export default {
  output: {
    disableFilenameHash: true,
  },
};

重新构建,产物的名称变为:

File                            Size         Gzipped
dist/static/css/187.css         126.99 KB    9.17 KB
dist/static/js/main.js          2.24 KB      922 B

output.enableInlineStyles

  • 类型:
type EnableInlineStyles =
  | boolean
  | RegExp
  | ((params: { size: number; name: string }) => boolean);
  • 默认值: false

用来控制生产环境中是否用 <style> 标签将产物中的 style 文件(.css 文件)inline 到 HTML 中。

注意,如果开启了这个选项,那么 style 文件将不会被写入产物目录中,而只会以 inline 样式的形式存在于 HTML 文件中。

示例

默认情况下,我们有这样的产物文件:

dist/html/main/index.html
dist/static/css/style.css
dist/static/js/main.js

开启 output.enableInlineStyles 选项后:

export default {
  output: {
    enableInlineStyles: true,
  },
};

产物文件将变成:

dist/html/main/index.html
dist/static/js/main.js

同时,dist/static/css/style.css 文件将被 inline 到 index.html 中:

<html>
  <head>
    <style>
      /* content of dist/static/css/style.css */
    </style>
  </head>
  <body></body>
</html>

通过正则匹配

当你需要内联产物中的一部分 CSS 文件时,你可以将 enableInlineStyles 设置为一个正则表达式,匹配需要内联的 CSS 文件的 URL。

比如,将产物中的 main.css 内联到 HTML 中,你可以添加如下配置:

export default {
  output: {
    enableInlineStyles: /\/main\.\w+\.css$/,
  },
};
TIP

生产环境的文件名中默认包含了一个 hash 值,比如 static/css/main.18a568e5.css。因此,在正则表达式中需要通过 \w+ 来匹配 hash。

通过函数匹配

你也可以将 output.enableInlineStyles 设置为一个函数,函数接收以下参数:

  • name:文件名,比如 static/css/main.18a568e5.css
  • size:文件大小,单位为 byte。

比如,我们希望内联小于 10KB 的资源,可以添加如下配置:

export default {
  output: {
    enableInlineStyles({ size }) {
      return size < 10 * 1000;
    },
  },
};

output.externals

  • 类型: string | object | function | RegExp
  • 默认值: undefined

在构建时,防止将代码中某些 import 的依赖包打包到 bundle 中,而是在运行时再去从外部获取这些依赖。

详情请见: webpack 外部扩展 (Externals)

示例

react-dom 依赖从构建产物中剔除。为了在运行时获取这个模块, react-dom 的值将全局检索 ReactDOM 变量。

export default {
  output: {
    externals: {
      'react-dom': 'ReactDOM',
    },
  },
};
TIP

当构建 Web Worker 产物时,externals 将不会生效。这是因为 Worker 环境不支持通过访问全局变量。

output.filename

  • 类型:
type FilenameConfig = {
  js?: string;
  css?: string;
  svg?: string;
  font?: string;
  image?: string;
  media?: string;
};
  • 默认值:
// 开发环境
const devDefaultFilename = {
  js: '[name].js',
  css: '[name].css',
  svg: '[name].[contenthash:8].svg',
  font: '[name].[contenthash:8][ext]',
  image: '[name].[contenthash:8][ext]',
  media: '[name].[contenthash:8][ext]',
};

// 生产环境
const prodDefaultFilename = {
  js: '[name].[contenthash:8].js',
  css: '[name].[contenthash:8].css',
  svg: '[name].[contenthash:8].svg',
  font: '[name].[contenthash:8][ext]',
  image: '[name].[contenthash:8][ext]',
  media: '[name].[contenthash:8][ext]',
};

设置构建产物的名称。

在生产环境构建后,会自动在文件名中间添加 hash 值,如果不需要添加,可以通过 output.disableFilenameHash 配置来禁用该行为。

下面是各个文件类型的说明:

  • js:表示 JavaScript 文件的名称。
  • css:表示 CSS 样式文件的名称。
  • svg:表示 SVG 图片的名称。
  • font:表示字体文件的名称。
  • image:表示非 SVG 图片的名称。
  • media:表示视频等媒体资源的名称。

示例

修改 JavaScript 文件的名称为 [name]_script.js

export default {
  output: {
    filename: {
      js:
        process.env.NODE_ENV === 'production'
          ? '[name]_script.[contenthash:8].js'
          : '[name]_script.js',
    },
  },
};
文件名中的 hash 值

通常来说,我们只会在生产环境下设置文件名的 hash 值(即 process.env.NODE_ENV === 'production' 时)。

如果你在开发环境下设置了文件名的 hash,那么可能会导致热更新不生效(尤其是 CSS 文件)。这是因为每次文件内容变化时,都会引起 hash 变化,导致 mini-css-extract-plugin 等工具无法读取到最新的文件内容。

异步模块的文件名

当你在代码中通过 dynamic import 的方式引入模块时,该模块会被单独打包成一个文件,它默认的命名规则如下:

  • 在开发环境下会基于模块路径生成名称,比如 dist/static/js/async/src_add_ts.js
  • 在生产环境下会是一个随机的数字 id,比如 dist/static/js/async/798.27e3083e.js,这是为了避免在生产环境中泄露源代码的路径,同时字符数也更少。
src/index.ts
const { add } = await import('./add.ts');

如果你希望为异步模块指定一个固定的名称,可以通过打包工具提供的 magic comments 来实现,通过 webpackChunkName 指定模块名称:

src/index.ts
const { add } = await import(
  /* webpackChunkName: "my-chunk-name" */ './add.ts'
);

通过以上写法指定模块名称后,生成的文件会是 dist/static/js/async/my-chunk-name.js

output.legalComments

  • 类型: 'linked' | 'inline' | 'none'
  • 默认值: 'linked'

配置 legal comment 的处理方式。

legal comment 是 JS 或 CSS 文件中的一些特殊注释,这些注释包含 @license@preserve,或是以 //! 开头。默认情况下,这些注释保留在输出文件中,因为这遵循了代码原作者的意图。

你可以通过 legalComments 来配置相关行为:

  • linked:将所有 legal comments 移至 .LEGAL.txt 文件并通过注释链接到它们。
  • inline:保留所有 legal comments。
  • none:移除所有 legal comments。

示例

移除所有 legal comments。

export default {
  output: {
    legalComments: 'none',
  },
};

output.overrideBrowserslist

  • 类型: string[] | Record<RsbuildTarget, string[]>
  • 默认值: undefined

指定项目兼容的目标浏览器范围。该值会被 @babel/preset-envautoprefixer 用来确定需要转换的 JavaScript 语法特性和需要添加的 CSS 浏览器前缀。

优先级

overrideBrowserslist 配置的优先级高于项目中的 .browserslistrc 配置文件和 package.json 中的 browserslist 字段。

大多数场景下,推荐优先使用 .browserslistrc 文件,而不是使用 overrideBrowserslist 配置。因为 .browserslistrc 文件是官方定义的配置文件,通用性更强,可以被社区中的其他库识别。

默认值

如果项目中没有定义任何 browserslist 相关的配置,也没有定义 overrideBrowserslist,那么 Rsbuild 会设置默认值为:

['chrome >= 87', 'edge >= 88', 'firefox >= 78', 'safari >= 14'];

示例

下面是兼容移动端 H5 场景的示例:

export default {
  output: {
    overrideBrowserslist: [
      'iOS >= 9',
      'Android >= 4.4',
      'last 2 versions',
      '> 0.2%',
      'not dead',
    ],
  },
};

可以查看 browserslist 文档 来了解如何自定义浏览器范围。

根据产物类型设置

当你同时构建多种类型的产物时,你可以为不同的产物类型设置不同的目标浏览器范围。此时,你需要把 overrideBrowserslist 设置为一个对象,对象的 key 为对应的产物类型。

比如为 webnode 设置不同的范围:

export default {
  output: {
    overrideBrowserslist: {
      web: [
        'iOS >= 9',
        'Android >= 4.4',
        'last 2 versions',
        '> 0.2%',
        'not dead',
      ],
      node: ['node >= 14'],
    },
  },
};

output.polyfill

  • 类型: 'entry' | 'usage' | 'off'
  • 默认值: 'usage'

通过 output.polyfill 选项,你可以控制 polyfills 的注入方式。

配置项

usage

output.polyfill 配置为 'usage' 时,Rsbuild 会在每个文件中根据代码中使用的 API 注入 polyfills。

export default {
  output: {
    polyfill: 'usage',
  },
};

entry

output.polyfill 配置为 'entry' 时,Rsbuild 会在每个入口文件中注入 polyfills。

export default {
  output: {
    polyfill: 'entry',
  },
};

off

output.polyfill 配置为 'off' 时,Rsbuild 不会注入 polyfills,开发者需要自行保证代码的兼容性。

export default {
  output: {
    polyfill: 'off',
  },
};

请查看 Polyfill 方案 了解详细内容。