Skip to content

Conversation

@camd
Copy link
Collaborator

@camd camd commented Dec 6, 2025

Notes from Cam

  1. The lines changed is only huge because of yarn.lock removal and pnpm-lock.yaml addition. Many of the files changed are just removing the hot reload.
  2. On that note: This PR would remove the need for a "hot reload" package like we have in fix: Update Hot reloading and react Helmet #9112. So that's another consideration.
  3. I did a bit of digging related to CI and our deployment infrastructure and this change should work well. But it will be telling if we try to deploy to prototype to test.

Migrate from Webpack to RSPack and Yarn to pnpm

Overview

This PR modernizes the Treeherder build infrastructure by:

  1. Migrating from Webpack to RSPack - A Rust-based bundler that is 5-10x faster while maintaining near-complete Webpack API compatibility
  2. Migrating from Yarn to pnpm - A more efficient and stricter package manager with better disk space usage and faster installs
  3. Cleaning up legacy dependencies - Removing deprecated packages and optimizing the dependency tree

Why RSPack?

RSPack is a high-performance JavaScript bundler written in Rust that offers:

  • 5-10x faster builds compared to Webpack
  • Near-complete Webpack API compatibility - minimal migration effort
  • Built-in SWC support - faster transpilation than Babel for the build process
  • Active development - backed by ByteDance, used in production at scale

Why pnpm?

pnpm offers several advantages over Yarn:

  • Faster installs - Up to 2x faster than npm/yarn
  • Disk space efficient - Uses hard links to save disk space
  • Stricter dependency management - Prevents phantom dependencies
  • Better monorepo support - Not relevant here, but future-proofing

Changes Made

Build System Migration

File Change
webpack.config.jsrspack.config.js Migrated to RSPack configuration with equivalent functionality
package.json Updated scripts to use rspack instead of webpack
.npmrc Added pnpm configuration file
.yarnrc Removed (no longer needed)
yarn.lockpnpm-lock.yaml Switched lockfile formats

RSPack Configuration Highlights

  • Uses builtin:swc-loader for faster JS/JSX transpilation (faster than Babel)
  • Uses @rspack/plugin-react-refresh for HMR (replaces react-hot-loader)
  • Maintains all existing functionality: code splitting, CSS extraction, dev server with proxy, etc.
  • Silences Sass @import deprecation warnings (Bootstrap 5 still uses @import)

Dependency Cleanup

Removed from dependencies (no longer needed)

  • react-hot-loader - Replaced by RSPack's built-in React Refresh

Removed from devDependencies

  • @babel/plugin-proposal-class-properties - Deprecated, built into @babel/preset-env
  • @babel/plugin-syntax-dynamic-import - Built into @babel/preset-env
  • path - Built-in Node.js module, unnecessary as a dependency

Moved to devDependencies (were incorrectly in dependencies)

  • eslint-formatter-codeframe - Only used by ESLint
  • globals - Only used by ESLint config
  • redux-mock-store - Only used in tests

Code Changes

Removed react-hot-loader usage from 8 files:

  • ui/App.jsx
  • ui/job-view/App.jsx
  • ui/login-callback/LoginCallback.jsx
  • ui/logviewer/App.jsx
  • ui/push-health/App.jsx
  • ui/intermittent-failures/App.jsx
  • ui/userguide/App.jsx
  • ui/perfherder/App.jsx

Configuration Updates

File Change
babel.config.json Simplified - removed deprecated plugins, using automatic JSX runtime
.prettierignore Added venv/, node_modules/, pnpm-lock.yaml
.circleci/config.yml Updated to use pnpm
docker/Dockerfile Updated to use pnpm
docs/*.md Updated documentation to reference pnpm commands

Testing

All scripts pass successfully:

Script Status
pnpm build ✅ Compiles with no errors or warnings
pnpm build:dev ✅ Compiles successfully
pnpm lint ✅ No linting errors
pnpm test ✅ All tests pass
pnpm start ✅ Dev server starts, HMR works
pnpm format:check ✅ All files formatted correctly
pnpm markdownlint ✅ No markdown issues

Build Performance Comparison

While exact benchmarks depend on hardware, RSPack typically provides:

  • Production build: ~1.7s (vs ~5-8s with Webpack)
  • Development build: ~1.3s (vs ~4-6s with Webpack)
  • HMR updates: Near-instant

Migration Guide for Developers

For local development

# Remove old dependencies
rm -rf node_modules yarn.lock

# Install pnpm if not already installed
npm install -g pnpm

# Install dependencies
pnpm install

# Start development server
pnpm start

Common commands (same as before, just use pnpm)

pnpm start          # Start dev server (connects to production API)
pnpm start:stage    # Start dev server (connects to staging API)
pnpm start:local    # Start dev server (connects to local backend)
pnpm build          # Production build
pnpm test           # Run tests
pnpm lint           # Run ESLint

Package Manager Enforcement

This PR adds guards to ensure developers use pnpm instead of yarn or npm.

How It Works

1. packageManager field in package.json

"packageManager": "[email protected]"

This field:

  • Blocks Yarn (classic) with a clear error message about Corepack
  • Signals to modern tools and CI systems which package manager to use
  • Is the standard way to declare package manager requirements per Node.js Corepack

2. preinstall script

"scripts": {
  "preinstall": "npx only-allow pnpm",
  ...
}

This script:

  • Runs before any install command
  • Provides a clear error message if someone tries to use npm or yarn
  • Works as a fallback for environments that don't respect packageManager

What Developers Will See

If they try to use Yarn:

error This project's package.json defines "packageManager": "[email protected]".
However the current global version of Yarn is 1.22.22.

Presence of the "packageManager" field indicates that the project is meant
to be used with Corepack...

If they try to use npm:

Use "pnpm" for installation in this project.

If you don't have pnpm, install it via "npm i -g pnpm".
For more details, go to https://pnpm.io/

Migration for Developers

# Remove old dependencies
rm -rf node_modules yarn.lock

# Install pnpm if not already installed
npm install -g pnpm

# Install dependencies
pnpm install

# Start development
pnpm start

Breaking Changes

None. The migration is transparent to end users and maintains all existing functionality.

Remaining Warnings (informational only)

  1. Peer dependency warnings - Several older React packages have peer deps for React 16/17. These work fine with React 18 but pnpm is stricter about reporting them.
  2. Node deprecation warning - util._extend deprecation from a transitive dependency. Does not affect functionality.

Future Improvements (out of scope for this PR)

  • Consider migrating from moment to dayjs for better tree-shaking
  • Consider upgrading react-router-dom to v6
  • Consider upgrading to newer versions of date picker, split pane, and table components that properly support React 18

@camd camd self-assigned this Dec 6, 2025
@camd camd requested review from Archaeopteryx and jmaher December 6, 2025 20:52
@camd camd force-pushed the camd/rspack-pnpm branch 4 times, most recently from 835ecec to 4945b72 Compare December 7, 2025 00:25
@codecov-commenter
Copy link

codecov-commenter commented Dec 7, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.95%. Comparing base (5d64caf) to head (085f554).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #9114   +/-   ##
=======================================
  Coverage   79.95%   79.95%           
=======================================
  Files         600      600           
  Lines       32560    32560           
  Branches     3310     3364   +54     
=======================================
  Hits        26032    26032           
+ Misses       6362     6357    -5     
- Partials      166      171    +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants