For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt, and this page is available as Markdown at /zh/guide/faq/features.md.
close
  • 简体中文
  • 功能类问题

    样式处理

    bundleless 模式如何跳过对 Less / Sass 等文件的预处理?

    bundleless 是指对每个源文件单独进行编译构建,可以理解为仅对源文件进行代码转换的过程。跳过对 .less/.scss 文件的预处理需要:

    1. 设置 source.entry.less/.scss 文件从入口里移除。
    2. 设置 output.copy.less/.scss 文件拷贝到产物目录。
    3. 设置 redirect.style.extensionfalse 禁用对 .less/.scss 文件导入路径的重定向行为。

    下面是一个跳过 .scss 文件处理的例子,src 里面所有的 .scss 文件都会被拷贝到产物目录下并且保留一致的相对路径。

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          // ...
          source: {
            entry: {
              index: ['./src/**', '!src/**/*.scss'],
            },
          },
          output: {
            copy: [{ from: '**/*.scss', context: path.join(__dirname, 'src') }],
          },
          redirect: {
            style: {
              extension: false,
            },
          },
        },
      ],
    });

    静态资源处理

    bundleless 模式如何跳过对静态资源文件的处理?

    在 bundleless 模式下,Rslib 默认会将静态资源文件转化为一个 JavaScript 文件和一个根据 output.distPath 输出的静态资源文件,并保留引用静态资源的 importrequire 语句。跳过对静态资源文件的上述处理需要:

    1. 设置 source.entry 将静态资源文件从入口里移除。
    2. 设置 output.copy 将静态资源文件拷贝到产物目录。
    3. 设置 redirect.asset.extensionfalse 禁用对静态资源文件导入路径的重定向行为。

    下面是一个跳过 .png 文件处理的例子,src 里面所有的 .png 文件都会被拷贝到产物目录下并且保留一致的相对路径。

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          // ...
          source: {
            entry: {
              index: ['./src/**', '!src/**/*.png'],
            },
          },
          output: {
            copy: [{ from: '**/*.png', context: path.join(__dirname, 'src') }],
          },
          redirect: {
            asset: {
              extension: false,
            },
          },
        },
      ],
    });

    代码压缩

    如何保留产物文件代码中的注释?

    默认情况下,Rslib 使用 SWC 清除注释,对应的 SWC 的 jsc.minify.format 配置为

    {
        comments: 'some',
        preserveAnnotations: true,
    }

    这将仅保留部分 legal 注释及 annotations。如果你想保留所有注释,可以参考如下配置:

    rslib.config.ts
    export default {
      lib: [
        // ...
      ],
      output: {
        minify: {
          jsOptions: {
            minimizerOptions: {
              format: {
                comments: 'all', // 将保留所有注释
              },
            },
          },
        },
      },
    };

    如何在保留代码可读性的同时,尽可能压缩产物体积?

    通过压缩代码可以减小产物体积,并提高加载速度,但是压缩后的代码可读性较差,不利于调试。如果你想保留代码可读性,可以通过如下配置,保留变量名并禁用压缩以方便调试。参考 web-infra-dev/rsbuild#966.

    rslib.config.ts
    export default {
      lib: [
        // ...
      ],
      output: {
        minify: {
          jsOptions: {
            minimizerOptions: {
              // 保留变量名并禁用压缩以方便调试
              mangle: false,
              minify: false,
              compress: true,
            },
          },
        },
      },
    };

    类型声明文件生成

    如何避免生成某些文件的类型声明文件?

    如下所示,Rslib 在构建 JavaScript 产物时忽略了 src/tests 目录下的文件,但这些文件仍然会生成对应的类型声明文件。

    rslib.config.ts
    export default {
      lib: [
        source: {
          entry: {
            index: ['src/**/*', '!src/tests/**/*'],
          }
        }
      ],
    };

    source.entry 设置的入口可以排除一些文件不生成对应的 JavaScript 产物,但无法排除生成对应的类型声明文件,这需要通过在 tsconfig.json 中设置 includeexclude 来实现,如下所示:

    tsconfig.json
    {
      "compilerOptions": {
        // ...
      },
      "include": ["src/**/*"],
      "exclude": ["src/tests/**/*"]
    }

    如果你想保留对这些文件的类型提示与检查,但不生成对应的类型声明文件,可以通过 extends 来继承一个基础的 tsconfig.json,然后覆盖 includeexclude 选项,如下所示:

    tsconfig.json
    {
      "compilerOptions": {
        // ...
      },
      "include": ["src/**/*", "rslib.config.ts"]
    }
    tsconfig.build.json
    {
      "extends": "./tsconfig.json",
      "compilerOptions": {
        // ...
      },
      "include": ["src/**/*"],
      "exclude": ["src/tests/**/*"]
    }

    新增的 tsconfig.build.json 需要配置在 rslib.config.ts 中的 source.tsconfigPath 选项中:

    rslib.config.ts
    export default {
      lib: [
        source: {
          entry: {
            index: ['src/**/*', '!src/tests/**/*'],
          }
        }
      ],
      source: {
        tsconfigPath: 'tsconfig.build.json',
      },
    };

    如何在 dts.bundletrue 时额外排除指定的依赖?

    Rslib 通过 rsbuild-plugin-dts 生成类型声明文件,该插件支持通过 output.externals 配置,从打包后的类型声明文件中排除指定的依赖。

    举个例子,若 @types/foo 仅声明在 devDependencies 中,按照 output.autoExternal 处理依赖的逻辑,在打包时 Rslib 会尝试将 @types/foo 一同打包进类型声明文件产物中,此时可以通过配置 output.externals 来排除 @types/foo

    rslib.config.ts
    export default {
      lib: [
        // ...
      ],
      output: {
        externals: ['@types/foo'],
      },
    };

    此外,如果只想指定某几个依赖项打包进类型声明文件产物中,可以通过配置 dts.bundle.bundledPackages 来实现,不在该配置中的所有其他依赖项都会被排除。

    为什么类型声明文件的目录结构不符合预期?

    类型声明文件的目录结构与 tsconfig.json 中的 rootDir 配置有关,如果未显式配置 rootDir,TypeScript 会进行自动推断,这可能导致输出结构与你的预期不符。

    例如,假设你的项目结构如下,当 composite 设置为 true 时,TypeScript 会将 rootDir 自动推断为项目根目录,此时类型声明文件会输出到 dist/src/index.d.ts

    .
    ├── dist
    │   └── src
    │       └── index.d.ts
    ├── src
    │   └── index.ts
    └── tsconfig.json

    你可以在 tsconfig.json 中显式设置 rootDir'./src',以确保类型声明文件输出到预期的 dist/index.d.ts

    tsconfig.json
    {
      "compilerOptions": {
        "rootDir": "./src"
      }
    }

    Rsbuild 插件

    为什么使用 modifyRsbuildConfig 修改配置不生效?

    Rslib 会在内部生成 Rsbuild 的 environments 配置,每一个 lib 数组中的配置项对应一个特定 environment 配置。

    modifyRsbuildConfig 是一个全局 hook,无法对特定 environment 下的配置生效,在 Rslib 中通常用于修改全局生效的 plugins 等。因此需要使用 modifyEnvironmentConfig 代替来修改特定 environment 的配置。

    参考 Environment 插件 了解如何开发一个 Environment 插件。

    其他

    如何在生成产物时保留源码中的 __webpack_hash__ 等模块变量?

    Rslib 底层使用的 Rspack,在构建时会默认将 __webpack_hash____webpack_nonce____webpack_public_path__模块变量 转换为包含 __webpack_require__ 的运行时代码。如果你需要在产物中保留这些模块变量,可以通过配置 source.define 来实现,如下所示:

    1. 在源码中将需要保留的模块变量替换为一个特征名称,如 __webpack_hash__ 替换为 WEBPACK_HASH__webpack_nonce__ 替换为 WEBPACK_NONCE__webpack_public_path__ 替换为 WEBPACK_PUBLIC_PATH 等。
    const isUpdateAvailable = () => lastCompilationHash !== __webpack_hash__; 
    const isUpdateAvailable = () => lastCompilationHash !== WEBPACK_HASH; 
    1. source.define 中添加需要保留的模块变量,传入的配置对象的键名是源码中替换后的变量名称,值是需要在产物中保留的模块变量。
    rslib.config.ts
    export default defineConfig({
      source: {
        define: {
          WEBPACK_HASH: '__webpack_hash__',
          WEBPACK_NONCE: '__webpack_nonce__',
          WEBPACK_PUBLIC_PATH: '__webpack_public_path__',
        },
      },
    });

    如何在生成产物时保留源码中的 __webpack_require__ 及其属性访问?

    Rslib 底层使用的 Rspack 会在构建时将 __webpack_require__ 及其属性访问识别为运行时变量。与 __webpack_hash__ 等模块变量不同,这类运行时变量无法通过 source.define 可靠地保留,需要通过占位符和 processAssets 进行处理:

    1. 在源码中将这些引用替换为唯一的占位符:
    src/index.ts
    const webpackRequire = __webpack_require__; 
    const webpackRequire = RSLIB_WEBPACK_REQUIRE; 
    
    __webpack_require__.i.push(handler); 
    RSLIB_INTERCEPT_MODULE_EXECUTION.push(handler); 
    1. 在 Rslib 配置中添加插件,通过 processAssets hook 还原占位符:
    rslib.config.ts
    import { defineConfig, rspack, type RsbuildPlugin } from '@rslib/core';
    
    const preserveWebpackRuntimePlugin: RsbuildPlugin = {
      name: 'preserve-webpack-runtime',
      setup(api) {
        api.processAssets(
          { stage: 'optimize-inline' },
          ({ assets, compilation, sources }) => {
            for (const [assetName, asset] of Object.entries(assets)) {
              if (!/\.[cm]?js$/.test(assetName)) continue;
    
              const source = asset.source().toString();
              const code = source
                .replaceAll('RSLIB_WEBPACK_REQUIRE', rspack.RuntimeGlobals.require)
                .replaceAll(
                  'RSLIB_INTERCEPT_MODULE_EXECUTION',
                  rspack.RuntimeGlobals.interceptModuleExecution,
                );
    
              if (code !== source) {
                compilation.updateAsset(assetName, new sources.RawSource(code));
              }
            }
          },
        );
      },
    };
    
    export default defineConfig({
      plugins: [preserveWebpackRuntimePlugin],
    });

    该插件会在 source map 生成后修改 JavaScript 产物,但不会同步更新 source map。开启 output.sourceMap 时,生成的映射可能不准确。

    RuntimeGlobals.require 对应 __webpack_require__RuntimeGlobals.interceptModuleExecution 对应 __webpack_require__.i。其他属性可参考 RuntimeGlobals 列表。如果某个属性没有对应的 RuntimeGlobals 值,可以在源码中写成 RSLIB_WEBPACK_REQUIRE.foo,插件会将其还原为 __webpack_require__.foo