5月27日 16:53

Rspack 的性能监控和调试是如何工作的?

Rspack 的性能监控和调试涉及构建耗时分析、产物体积优化和运行时问题排查。以下从核心工具、配置方法和实战技巧三个维度展开。

构建性能分析

RSPACK_PROFILE 环境变量

Rspack 内置了基于环境变量的性能分析能力,无需安装额外依赖:

bash
# 生成构建各阶段耗时日志 RSPACK_PROFILE=ALL rspack build

执行后在项目根目录生成 .rspack-profile-${timestamp}-${pid} 文件夹,其中 rspack.log 记录了构建各阶段的耗时数据,可以直接定位耗时最长的环节。

如果需要更细粒度的分析,可以使用 Perfetto 生成可视化 trace:

bash
RSPACK_PROFILE=TRACE=layer=perfetto rspack build

这会生成 rspack.pftrace 文件,上传到 ui.perfetto.dev 即可以时间轴形式查看每个构建步骤的耗时分布。

还可以按模块过滤 trace,只关注特定环节:

bash
# 只看编译阶段的 trace RSPACK_PROFILE='TRACE=layer=logger&filter=rspack_core::compiler::compilation' rspack build # 只看 chunk 图构建 RSPACK_PROFILE='TRACE=filter=[build_chunk_graph]' rspack build # 调试模块解析 RSPACK_PROFILE='TRACE=filter=rspack_resolver=trace&layer=logger' rspack build

Rsdoctor 构建分析工具

Rsdoctor 是 Rspack 生态专用的构建分析工具,可以直观展示编译时间、编译前后代码变化、模块引用关系和重复模块:

bash
npm install @rsdoctor/rspack-plugin -D
javascript
const { RsdoctorPlugin } = require('@rsdoctor/rspack-plugin'); module.exports = { plugins: [ new RsdoctorPlugin({ // 构建完成后自动打开分析报告 disableClientServer: false, }), ], };

构建完成后会自动打开浏览器展示分析面板,包含模块编译耗时排行、重复依赖检测和产物体积分布等视图。

Stats JSON 输出

通过 --profile 参数输出构建统计:

bash
npx rspack build --profile --json > stats.json

配合 webpack-bundle-analyzer 可视化分析产物体积:

javascript
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); module.exports = { plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false, reportFilename: 'bundle-report.html', }), ], };

构建统计配置

Rspack 的 stats 选项控制构建输出的信息粒度:

javascript
module.exports = { stats: { colors: true, timings: true, // 显示各阶段耗时 builtAt: true, // 构建时间戳 assets: true, // 输出资源列表 assetsSort: 'size', // 按体积排序 modules: true, // 模块信息 chunks: true, // chunk 信息 reasons: true, // 模块引入原因 errors: true, errorDetails: true, warnings: true, // 日志级别控制 logging: 'warn', loggingDebug: /rspack/, // 缓存命中信息 cached: true, cachedAssets: true, }, };

loggingloggingDebug 配合使用可以在 warn 级别下单独开启特定模块的详细日志,减少无关输出。

Source Map 与开发调试

Source Map 配置

javascript
module.exports = { mode: 'development', devtool: 'eval-cheap-module-source-map', };

eval-cheap-module-source-map 在开发模式下兼顾重建速度和调试体验。生产环境建议使用 hidden-source-map 配合错误监控平台使用。

开发服务器错误覆盖

javascript
module.exports = { devServer: { client: { overlay: { errors: true, warnings: false, }, }, }, };

开启后编译错误会直接覆盖在浏览器页面上,无需切换到终端查看。

缓存与线程池调优

文件系统缓存

javascript
module.exports = { cache: { type: 'filesystem', profile: true, // 输出缓存耗时信息 }, };

开启 profile: true 后,stats 中会包含缓存命中和未命中的耗时对比,帮助判断缓存效果。

线程池配置

Rspack 底层使用 Tokio(异步 I/O)和 Rayon(CPU 密集任务)两套线程池,可通过环境变量调整:

bash
# 限制工作线程数,适用于 CI 等资源受限环境 TOKIO_WORKER_THREADS=4 RAYON_NUM_THREADS=4 rspack build # 调整阻塞线程池大小(默认为 4) RSPACK_BLOCKING_THREADS=2 rspack build

线程数并非越大越好。在容器化部署或共享 CI 机器上,过高的并行度反而会因为线程上下文切换导致性能下降。

常见性能问题与解决

构建速度慢

排查思路:先用 RSPACK_PROFILE=ALL 或 Rsdoctor 定位耗时环节,再针对性优化。

典型原因与方案

  • JS Loader 开销大:用 Rspack 内置的 builtin:swc-loader 替代 babel-loader,用 builtin:lightningcss-loader 替代 postcss-loader,可显著减少 Loader 编译耗时
  • 缓存未启用:开启 cache: { type: 'filesystem' }
  • 模块解析路径过长:配置 resolve.modulesresolve.extensions 减少查找范围
  • Loader 作用范围过大:用 rules[].include 限定 Loader 只处理必要的文件
javascript
module.exports = { resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'], extensions: ['.js', '.jsx', '.ts', '.tsx'], }, module: { rules: [ { test: /\.tsx?$/, include: path.resolve(__dirname, 'src'), use: 'builtin:swc-loader', }, ], }, };

内存占用高

  • Source Map 配置过高:开发环境用 eval-cheap-source-map 而非 source-map
  • 并行度过高:降低 parallelism 值或调整 RAYON_NUM_THREADS
  • 关闭不必要的优化:optimization.removeAvailableModules: false 可减少二次处理
javascript
module.exports = { devtool: 'eval-cheap-source-map', parallelism: 4, optimization: { removeAvailableModules: false, removeEmptyChunks: false, }, };

打包体积大

  • 开启 Tree Shaking:optimization.usedExports: true + optimization.sideEffects: true(需在 package.json 中标记 "sideEffects": false
  • 配置代码分割:使用 splitChunks 将第三方库分离
  • 按需加载:使用动态 import() 实现路由级懒加载
javascript
module.exports = { optimization: { usedExports: true, sideEffects: true, splitChunks: { chunks: 'all', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, }, }, }, }, };

自定义调试插件

当内置工具无法满足需求时,可以通过 Rspack 的 Hook 机制编写调试插件:

javascript
class DebugPlugin { apply(compiler) { compiler.hooks.compilation.tap('DebugPlugin', (compilation) => { console.log('[Debug] Compilation started'); }); compiler.hooks.done.tap('DebugPlugin', (stats) => { const { errors, warnings } = stats.compilation; console.log(`[Debug] Build completed — errors: ${errors.length}, warnings: ${warnings.length}`); }); } } module.exports = { plugins: [new DebugPlugin()], };

逐步调试法也是常用手段:先用最小配置启动构建确认基线正常,再逐步添加 Loader、Plugin 和优化选项,每次只加一项,出问题时立即定位到新增配置。

性能基准与持续监控

建立构建性能基准

javascript
const { execSync } = require('child_process'); function benchmark() { const iterations = 5; const times = []; for (let i = 0; i < iterations; i++) { const start = Date.now(); execSync('npx rspack build'); times.push(Date.now() - start); } const avg = times.reduce((a, b) => a + b, 0) / iterations; console.log(`Avg: ${avg}ms, Min: ${Math.min(...times)}ms, Max: ${Math.max(...times)}ms`); } benchmark();

将基准数据纳入 CI 流程,当构建耗时出现显著回退时自动告警,比人工感知更可靠。

生成性能报告

javascript
const fs = require('fs'); const path = require('path'); function generateReport(stats) { const report = { timestamp: new Date().toISOString(), buildTime: stats.time, modules: stats.modules.length, assets: stats.assets.map((a) => ({ name: a.name, size: a.size })), warnings: stats.warnings.length, errors: stats.errors.length, }; fs.writeFileSync( path.join(__dirname, 'performance-report.json'), JSON.stringify(report, null, 2) ); }

定期收集性能报告并对比历史数据,可以及时发现构建性能的劣化趋势。

Rspack 的性能监控与调试体系以 RSPACK_PROFILE 和 Rsdoctor 为核心,配合 Source Map、缓存、线程池调优以及自定义插件,覆盖了从定位瓶颈到验证优化的完整链路。掌握这些工具的关键在于先用分析工具定位问题,再针对性地调整配置,避免盲目优化。

标签:Rspack