Boosting build speed by over 50% by migrating to Rsbuild

Introduction

In today's fast-paced development environment, build performance is crucial for developer productivity and deployment efficiency. Our team recently undertook a significant migration from Create React App (CRA) to Rsbuild, resulting in a remarkable 50%+ improvement in build times. This blog post outlines our journey, the challenges we encountered, and the lessons we learned during this migration.

Overview of the current stack

Core Architecture

  • Micro Frontend Architecture: Built using Module Federation with multiple micro-frontends for different modules

  • React 18

  • TypeScript

  • Create React App (CRA) with react-app-rewired for configuration overrides

  • npm with Node.js 22.x

UI & Styling

  • Design System: Custom design system built as a wrapper around Ant Design

  • Styling: Less preprocessor for AntD overrides and Tailwind for the main styling

  • Monaco Editor for advanced code editing capabilities

  • Day.js for lightweight date manipulation

State Management & Data

  • State Management: Redux with Redux Saga for side effects

  • Data Fetching: TanStack React Query for server state management

  • Internationalization: i18next for multi-language support

Why We Needed This Migration?

The Problem with CRA

Our existing setup had several critical issues that were impacting our development workflow:

  1. CRA Deprecation: Create React App is officially deprecated, meaning no new features or security updates

  2. Slow Build Times: Our webpack-based builds were taking an average of 15 minutes to complete

  3. Bloated Configuration: Complex webpack overrides using react-app-rewired were becoming unmaintainable

Impact

  • Customer Impact: Delays in fixing bugs due to slow build times were affecting customers. This led to frustration and a decrease in user satisfaction, as customers had to wait longer for improvements/fixes.

  • Developer Productivity: Long build times significantly reduce developer velocity

Why We Chose Rsbuild?

After evaluating several alternatives, we chose Rsbuild for the following reasons:

1. Performance Benefits

  • Rust-based Rspack: Underlying bundler written in Rust, providing ~50% faster builds compared to webpack

  • Optimized Architecture: Built specifically for modern web development with performance in mind

2. Seamless Migration Path

  • Webpack Compatibility: Rspack offers a webpack-compatible API, making migration smoother, and most popular webpack plugins are already supported

  • CRA Migration Guide: Comprehensive migration documentation available at rsbuild.rs/guide/migration/cra

3. Out-of-the-Box Features

  • Module Federation: Native support for micro-frontend architecture

  • Less Support: Built-in Less preprocessor support

  • Tree Shaking & Code Splitting: Advanced optimization features

  • TypeScript: First-class TypeScript support

4. Future-Proof Architecture

  • Plugin-based System: Extensible architecture for future enhancements

  • Active community: Regular updates and active community support (300k+ weekly downloads)

  • Modern Tooling: Built for the modern web development ecosystem

Migration Plan & Strategy

Phase 1: Foundation Setup

Following the official Rsbuild CRA migration guide, we:

  1. Replaced Dependencies:

     npm remove react-scripts
     npm add @rsbuild/core @rsbuild/plugin-react -D
    
  2. Updated Scripts:

     {
       "scripts": {
         "start": "rsbuild dev",
         "build": "rsbuild build",
         "preview": "rsbuild preview"
       }
     }
    
  3. Created Configuration:

     // rsbuild.config.ts
     import { defineConfig } from '@rsbuild/core';
     import { pluginReact } from '@rsbuild/plugin-react';
    
     export default defineConfig({
       plugins: [pluginReact()],
     });
    

Phase 2: Plugin Migration Analysis

We identified and migrated our webpack plugins:

Removed Plugins (native Rsbuild support):

  • babel-plugin-transform-remove-console β†’ performance.removeConsole

  • worker-loader β†’ Native web worker support

Migrated Plugins:

  • Module Federation β†’ @module-federation/rsbuild-plugin

  • Less loader β†’ @rsbuild/plugin-less

  • Node polyfills β†’ @rsbuild/plugin-node-polyfill

Phase 3: Staged Rollout

  • Staging Environment: Deployed changes to staging for initial testing

  • Beta Environment: Extended testing in the beta environment

  • Traffic Analysis: Monitored for one week to identify potential issues

  • Production Deployment: Gradual rollout to production

Challenges Faced & Solutions

1. Plugin and Loader Compatibility

  • Challenge: Not all webpack plugins or loaders are directly compatible with Rsbuild/Rspack.

  • Guideline: Audit your current plugins and loaders, and check for native support or recommended alternatives in Rsbuild. Be prepared to refactor or remove plugins that are no longer necessary or supported.

  • Example: We found that plugins like babel-plugin-transform-remove-console and worker-loader were no longer needed, as Rsbuild provided native support for these features.

2. Styling and CSS Handling

  • Challenge: Differences in how CSS modules, preprocessors (like Less), and global styles are handled can lead to unexpected styling issues.

  • Guideline: Review your styling approach, especially for global overrides and CSS module conventions. Test your styles thoroughly after migration and adjust configurations as needed.

  • Example: Some global Less overrides for Ant Design were not being applied as expected due to differences in how global selectors were processed, which required us to adjust our style definitions and loader settings.

3. Micro-Frontend Integration

  • Challenge: Ensuring consistent and singleton usage of shared dependencies across micro-frontends is critical to avoid runtime issues.

  • Guideline: Align dependency versions and configurations across all MFEs, and use best practices for sharing libraries and assets.

  • Example: We encountered issues with multiple instances of libraries like dayjs being loaded in different MFEs, which led to inconsistent behavior in date pickers.

4. Third-Party Library Support

  • Challenge: Some third-party libraries or plugins may not work out of the box with Rsbuild.

  • Guideline: Check the compatibility of critical libraries early in the migration process. Look for modern, actively maintained alternatives if needed, and plan for isolated testing of such dependencies.

  • Example: Our existing code editor integration relied on a plugin that was not compatible with Rsbuild, prompting us to migrate to a newer, supported alternative.

Deployment Strategy πŸš€

Pre-Migration Preparation

Before starting the Rsbuild migration, we established a comprehensive deployment strategy to ensure minimal disruption:

Staged Deployment Approach

Phase 1: Internal Testing (Week 1-2)

  • We first tested the Rsbuild changes in the local dev server

  • Comprehensive testing across all features and user flows

  • Performance Benchmarking: Measured build times, bundle sizes, and runtime performance

Phase 2: Staging Environment (Week 3)

  • Deployed the Rsbuild version to the staging environment

  • QA Testing: Manual QA testing and automation suites were run to identify any issues.

  • Integration Testing: Verified all micro-frontend integrations worked correctly

Phase 3: Beta Environment (Week 4)

  • Deployed the Rsbuild version to the beta environment

  • QA Testing: Manual QA testing and automation suites were run on more production-level data.

  • Error Rate Monitoring: Closely monitored error rates and performance metrics

Phase 4: Production Rollout (Week 5)

  • Maintenance window: Although we did not expect any downtime with this migration, we decided to provide a maintenance window communication to ensure safety and a better customer experience. The maintenance window was strategically chosen by analyzing user traffic data to ensure it’s during non-critical business hours.

  • Real-time Monitoring: Continuous error monitoring during the rollout period

  • Rollback plan: We already have a rollback strategy for deployments, so we decided to stick with it.

Post-Deployment Validation

Automated Health Checks

  • Smoke Tests: Automated tests for critical user flows

  • Performance Tests: Automated performance regression tests

Manual Validation Checklist

  • [ ] All major user flows work correctly

  • [ ] Performance metrics meet or exceed baseline

  • [ ] Error rates remain within acceptable thresholds

  • [ ] All integrations (APIs, third-party services) function properly

Lessons Learned from Deployment

What Went Well

  • Staged Approach: Gradual rollout helped identify issues early

  • Monitoring: Comprehensive monitoring caught issues before they affected users

  • Rollback Plan: Having a solid rollback strategy provided confidence during deployment

Areas for Improvement

  • Testing Coverage: Could have benefited from more automated integration tests

  • Performance Baselines: Should have established clearer performance benchmarks

  • Communication: Could have improved stakeholder communication during the rollout

Results πŸŽ‰

Build Time Improvements

Production Build: Reduced from ~8 minutes to ~3 minutes (>60% improvement)

Developer Experience

  • Faster Feedback Loop: Quicker development iterations

Conclusion

Our migration from CRA to Rsbuild was a significant success, resulting in 50%+ improvement in build times and a more modern, maintainable build system. While the migration presented several challenges, the benefits far outweighed the effort:

  • Faster Development: Reduced build times significantly improved developer productivity

  • Modern Tooling: Access to the latest web development features and optimizations

  • Future-Proof: Active development and community support ensure long-term viability

The key to success was a well-planned migration strategy, thorough testing, and addressing issues incrementally. For teams considering similar migrations, we recommend:

  1. Start with the official migration guide

  2. Plan for plugin compatibility issues

  3. Implement a staged rollout strategy

  4. Monitor performance metrics throughout

  5. Have rollback plans ready

The migration has positioned our team for better performance, faster development cycles, and access to modern web development tools. The investment in migration has already paid dividends in improved developer experience and deployment efficiency.

What's Next?

Here are some of the next steps we are considering:

  1. Adopting Faster Package Managers

    • We are exploring switching from npm to pnpm for dependency management.
  2. Optimizing Dependencies

    • Regularly audit and prune unused dependencies/code, and consider splitting large dependencies or lazy-loading rarely used modules to keep the build lean.
  3. Fine-Tuning Module Federation

    • Analyze our micro-frontend boundaries and shared dependencies to ensure optimal code splitting and minimal duplication across MFEs, reducing both build and runtime bundle sizes.
  4. Parallelizing CI/CD Steps

    • Refactor CI/CD pipelines to maximize parallelism, such as running linting, testing, and building steps concurrently where possible.
  5. Profiling and Monitoring

    • Continuously profile build performance using tools like Webpack Bundle Analyzer or Rsbuild’s Rsdoctor to identify new bottlenecks as the codebase evolves.
0
Subscribe to my newsletter

Read articles from Kanishka Chowdhury directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kanishka Chowdhury
Kanishka Chowdhury

UI Engineer currently simplifying the process of building generative AI bots @yellow.ai. On a journey to make the web a better place by building engaging and performant UIs.