
Rspack Tracing
- 188 installs
- 86 repo stars
- Updated August 4, 2026
- rstackjs/agent-skills
Use rspack-tracing for development tasks
About
rspack-tracing: A skill for development. This provides functionality for development workflows.
- rspack-tracing
Rspack Tracing by the numbers
- 188 all-time installs (skills.sh)
- +6 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #2,122 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rstackjs/agent-skills --skill rspack-tracingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 188 |
|---|---|
| repo stars | ★ 86 |
| Last updated | August 4, 2026 |
| Repository | rstackjs/agent-skills ↗ |
What it does
Use rspack-tracing for development tasks
Files
Rspack Tracing & Performance Profiling
When to Use This Skill
Use this skill when you need to:
1. Diagnose why an Rspack build is slow. 2. Understand which plugins or loaders are taking the most time. 3. Analyze a user-provided Rspack trace file. 4. Guide a user to capture a performance profile.
Workflow
1. Capture a Trace
First, ask the user to run their build with tracing enabled.
# Set environment variables for logging to a file
RSPACK_PROFILE=TRACE RSPACK_TRACE_LAYER=logger RSPACK_TRACE_OUTPUT=./trace.json pnpm buildThis will generate a trace file in a timestamped directory like .rspack-profile-{timestamp}-{pid}/trace.json.
See references/tracing-guide.md for more details on configuration.
2. Quick Diagnosis for Crashes/Errors
If the user wants to identify which stage a crash or error occurred in, use tail to quickly view the last events without running the full analysis:
# Navigate to the generated profile directory
cd .rspack-profile-*/
# View the last 20 events to see where the build failed
tail -n 20 trace.jsonThe last events will show the span names and targets where the build stopped, helping to quickly pinpoint the problematic stage, plugin, or loader.
3. Full Performance Analysis
For detailed performance profiling (not just crash diagnosis), ask the user to run the bundled analysis script on the generated trace file.
# Navigate to the generated profile directory
cd .rspack-profile-*/
# Run the analysis script
node ${CLAUDE_PLUGIN_ROOT}/skills/tracing/scripts/analyze_trace.js trace.json4. Interpret Results
Use the output from the script to identify bottlenecks. Consult references/bottlenecks.md to map span names to actionable fixes.
5. Locate Slow Plugins
Based on the "Top Slowest Hooks" from the analysis script:
1. Identify the Hook: Note the hook name (e.g., hook:CompilationOptimizeChunks). 2. Inspect Configuration: Read rspack.config.js or rsbuild.config.ts. 3. Map Hook to Plugin: Look for plugins and their sources that tap into that specific hook. 4. Output: Output the paths, lines and columns of the suspected plugin source code.
Common Scenarios & Quick Fixes
- Bottleneck Reference: Mapping spans to concepts.
- Tracing Guide: Detailed usage of
RSPACK_PROFILE.
Understanding Rspack Performance Bottlenecks
This reference maps internal Rspack tracing spans to high-level concepts to help you identify performance issues.
Core Compilation Phases
| Span Name | Description | Potential Bottlenecks |
|---|---|---|
tracing::profiling | The entire build process. | Overall slowness. |
compiler::make | Make Phase: Resolving, loading, and parsing modules. | Heavy loaders (babel/swc with complex configs), too many files, slow file system. |
compiler::seal | Seal Phase: Optimizing, splitting chunks, generating code. | Complex code splitting, heavy minification, many modules. |
compiler::emit_assets | Emit Phase: Writing files to disk. | Slow disk I/O, huge output files. |
Detailed Spans
Make Phase (Module Processing)
resolver::resolve: Resolving import paths.- High Time?: Check for complex
resolve.aliasorresolve.modules, or too many standard fallbacks. loader::run_loaders: Executing loaders (JavaScript/Rust).- High Time?: Identify which loader is slow. If
sass-loaderorbabel-loaderis slow, consider caching (cache: truein config) or usingswc-loader. parser::parse: Parsing source code into AST.- High Time?: Large files?
Seal Phase (Optimization)
compilation::code_generation: Generating final code from AST.compilation::optimize_chunks: Splitting chunks (SplitChunksPlugin).k_means_splitter: If you see this, complex splitting logic is running.js_minimizer: Minification (SwcJsMinimizer).- High Time?: Disable minimization in dev (
optimization.minimize: false) for speed.
General
read_file: Reading files from disk.write_file: Writing artifacts to disk.
Common Fixes
1. Slow `make` phase:
- Use
experiments.cache(Persistent Cache). - Exclude
node_modulesfrom expensive loaders. - Switch to lighter loaders (e.g.
swc-loadervsbabel-loader).
2. Slow `seal` phase:
- Reduce
splitChunkscomplexity. - Disable
sourcemapin production if acceptable cost. - Upgrade to latest Rspack (performance improvements are frequent).
Rspack Tracing Guide
Tracing allows you to visualize exactly what Rspack is doing during a build.
Enabling Tracing
Rspack uses several environment variables to control tracing.
Command:
RSPACK_PROFILE=TRACE RSPACK_TRACE_LAYER=logger RSPACK_TRACE_OUTPUT=./trace.json rspack buildVariables
`RSPACK_PROFILE`: Controls the granularity of the trace.
TRACE: Captures all spans. (Recommended for deep analysis)DEBUG,INFO,WARN,ERROR,CRITICALOFF: Disables tracing.
`RSPACK_TRACE_LAYER`: Controls the output format.
logger: Outputs standard JSON logging (required for the analysis script).
Output
After running the command, Rspack will generate the file specified in RSPACK_TRACE_OUTPUT.
Using the Skill's Analysis Tool
This skill includes a script to summarize the trace file.
# Run the included script
node scripts/analyze_trace.js <path-to-trace-file>#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Parse duration string (e.g., "1.23ms", "456.78µs", "0.12s") to milliseconds
function parseDuration(durationStr) {
if (!durationStr) return 0;
const match = durationStr.match(/^([\d.]+)(ms|µs|s|ns)$/);
if (!match) return 0;
const value = parseFloat(match[1]);
const unit = match[2];
switch (unit) {
case 's': return value * 1000;
case 'ms': return value;
case 'µs': return value / 1000;
case 'ns': return value / 1000000;
default: return value;
}
}
// Get trace file path
const tracePath = process.argv[2] || path.join(__dirname, 'trace.json');
if (!fs.existsSync(tracePath)) {
console.error(`Error: Trace file not found at ${tracePath}`);
console.error('Usage: node analyze_trace.js <path-to-trace.json>');
process.exit(1);
}
console.log(`Analyzing trace file: ${tracePath}\n`);
try {
const fileContent = fs.readFileSync(tracePath, 'utf8');
// Parse line-delimited JSON
const events = fileContent.trim().split('\n')
.map(line => {
try { return JSON.parse(line); }
catch(err) { return null; }
})
.filter(Boolean);
if (!events.length) {
console.error("No valid trace events found.");
process.exit(1);
}
console.log("=== Rspack Build Performance Analysis ===\n");
console.log(`Total events: ${events.length}\n`);
// Categorize events by target
const pluginStats = new Map();
const loaderStats = new Map();
events.forEach(event => {
const target = event.target;
const timeField = event.fields?.['time.busy'];
if (!timeField) return;
const duration = parseDuration(timeField);
if (target === 'Plugin Analysis') {
// Plugin performance
const pluginName = event.span?.name;
if (!pluginName) return;
if (!pluginStats.has(pluginName)) {
pluginStats.set(pluginName, {
count: 0,
total: 0,
max: 0,
min: Infinity
});
}
const stat = pluginStats.get(pluginName);
stat.count++;
stat.total += duration;
stat.max = Math.max(stat.max, duration);
stat.min = Math.min(stat.min, duration);
} else if (target === 'Loader Analysis') {
// Loader performance
let loaderName = event.span?.name;
// For pitch phase (span.name is null), use resource path
if (!loaderName) {
const resource = event.fields?.resource;
if (resource) {
// Extract filename from resource path
const cleanResource = resource.replace(/^"|"$/g, ''); // Remove quotes
const filename = cleanResource.split('/').pop();
loaderName = `Loader pitch for ${filename}`;
} else {
loaderName = 'Loader pitch (unknown resource)';
}
}
if (!loaderStats.has(loaderName)) {
loaderStats.set(loaderName, {
count: 0,
total: 0,
max: 0,
min: Infinity
});
}
const stat = loaderStats.get(loaderName);
stat.count++;
stat.total += duration;
stat.max = Math.max(stat.max, duration);
stat.min = Math.min(stat.min, duration);
}
});
// Display Plugin Analysis
if (pluginStats.size > 0) {
console.log("🔌 Plugin Analysis (by name):");
console.log("─".repeat(80));
const sortedPlugins = [...pluginStats.entries()]
.sort((a, b) => b[1].total - a[1].total);
sortedPlugins.forEach(([name, stat]) => {
const avg = stat.total / stat.count;
console.log(`${name}`);
console.log(` Total: ${stat.total.toFixed(2)}ms | Count: ${stat.count} | ` +
`Avg: ${avg.toFixed(2)}ms | Max: ${stat.max.toFixed(2)}ms | Min: ${stat.min.toFixed(2)}ms`);
console.log("");
});
const totalPluginTime = [...pluginStats.values()]
.reduce((sum, stat) => sum + stat.total, 0);
console.log(`Total Plugin Time: ${totalPluginTime.toFixed(2)}ms\n`);
}
// Display Loader Analysis
if (loaderStats.size > 0) {
console.log("\n🔧 Loader Analysis (by name):");
console.log("─".repeat(80));
const sortedLoaders = [...loaderStats.entries()]
.sort((a, b) => b[1].total - a[1].total);
sortedLoaders.forEach(([name, stat]) => {
const avg = stat.total / stat.count;
console.log(`${name}`);
console.log(` Total: ${stat.total.toFixed(2)}ms | Count: ${stat.count} | ` +
`Avg: ${avg.toFixed(2)}ms | Max: ${stat.max.toFixed(2)}ms | Min: ${stat.min.toFixed(2)}ms`);
console.log("");
});
const totalLoaderTime = [...loaderStats.values()]
.reduce((sum, stat) => sum + stat.total, 0);
console.log(`Total Loader Time: ${totalLoaderTime.toFixed(2)}ms\n`);
}
} catch (err) {
console.error("Error processing trace file:", err);
process.exit(1);
}