To run this benchmark yourself, clone web-infra-dev/bundler-benchmark and then use this command from the root:

./scripts/ ${platform} # `platform` is used to uniquely identify the generated benchmark data.

Benchmark case


This project is used for comparing development mode and production mode build performance. It is combined by several sub projects atlaskit-editor, common-libs, common-libs-chunks, rome and esbuild-three, which has a total of 50000 modules. here is the simple description of each sub project:


Basic react application with @atlaskit/editor-core


A application that used some common libraries in JavaScript ecosystem.


Same as common-libs, but using async import() syntax to force bundler generate multiple chunks.


A large JavaScript codebase by duplicating the three.js library 10 times.


The old Rome code base (prior to their Rust rewrite) to approximate a large TypeScript codebase.


Tested on Intel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz 32Core, 64GB of RAM

moderspackwebpack(with swc)webpack (with babel)
development cold start3.79s31.25s42.61s
production cold start22.353s75.054s160.059s


10000 react components (each component only have basic skeleton) to test hot module replacement performance of each devServer of bundler.


Tested on Intel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz 32Core, 64GB of RAM

rspack/rootrspack/leafwebpack(with swc)/rootwebpack (with swc)/leafwebpack (with babel)/rootwebpack (with babel)/leaf


  • dev-cold-start: the time it takes for the development build to complete without caching.
  • production-build-cold-start: the time it takes for the production build to complete without caching.
  • HMR: the time it takes for the development server rebuild the project when an update is applied to a source file. there are two sub metrics of HMR:
    • leaf: time for updating a react component file that has no dependency
    • root: time for updating a root react component, normally it is named App.tsx or index.tsx

Bundler involved in comparison

  • webpack + ts-loader (or babel-loader in react-components-10000) + terser-webpack-plugin

  • webpack + swc-loader + swc-minifier

  • rspack(using swc as transpiler and swc minifier)

All the configuration in development mode keep as is except the loader which dependends on the test target.

In production mode we set devtool to source-map and use loader and minifier dependends on the test target, keep other configuration as is.



Using hyperfine to run each development build command 10 times with warmup and get the average time, finally generate corresponding markdown table.


Using hyperfine to run each production build command 10 times with warmup and get the average time, finally generate corresponding markdown table.


The HMR benchmark is relatively complex because it is usually implemented in four stages.

  1. devServer listens for file changes and rebuilds the project (usually a partial build).
  2. devServer sends the built diff to the HMR client over the local network (usually a websocket).
  3. HMR client receives the diff and applies the diff to runtime code of the browser.
  4. the browser rerendering the view.

Sometimes it takes about half time of HMR from second stage to fourth stage.

Some tools' HMR benchmarks use the entire HMR time as the metric time, and since each toolchain may implement each stage of HMR differently, it's fine to compare in this way.

However, our implementation is basically the same as webpack's in phases two through four, unlike webpack, Rspack uses a more fine-grained incremental build algorithm to accelerate phase one, and to better demonstrate the effect of this algorithm, we use the re-build time of both build tools as a metric.