DEV Community

Krzysztof Sordyl
Krzysztof Sordyl

Posted on

How I migrated from CRA to RSBuild

I recently revisited an old personal React project and discovered it was built using Create React App (CRA).
While considering a switch to Vite for its performance benefits, I stumbled upon RSBuild, which, according to its documentation, is even faster: RSBuild Performance.

Why RSBuild ?

Here are my key reasons for choosing RSBuild:

  1. Performance: It's designed for speed.
  2. CRA is Outdated: The last CRA release was on April 12, 2022
  3. Migration Guide: RSBuild provides a detailed guide for seamless migration.
  4. Batteries included: I don’t need to worry about additional integration, RSBuild covers what I need

Few words about RSBuild

RSBuild is based on RSPack, a Rust-written bundler optimized for web development. It's user-friendly and minimizes configuration needs.

Being framework-agnostic, RSBuild offers a robust plugin system. For React integration, I simply added plugins: [pluginReact()], in rsbuild.config.ts.

RSBuild's comprehensive documentation includes examples and detailed guides for migrating from:

  • Webpack
  • Create React App (CRA)
  • Vue CLI
  • Modern Builder

CSS

In my CRA project, I utilized css-modules. Fortunately, RSBuild supports it out of the box, so no extra effort was required on my part.

Environment Variables

My project only had two environments, and I wanted to move away from the REACT_APP prefix. RSBuild allowed me to easily switch to using PUBLIC as the prefix, treating all my environment variables as public, which suited my project's needs.

Testing

RSBuild doesn't integrate testing frameworks directly. Thus, there's no straight swap for react-scripts test. I set up Jest independently. To manage this, I used a separate .env.test file for test configurations. To avoid additional tooling with ts-node, I relied on standard CJS files:

I have stick with good old CJS files:

  • The first file is for loading environment variables:
// src/config/loadEnvs.js

const dotenv = require('dotenv')
const path = require('path')

const loadEnvs = (mode) => {
  const testOptions = mode === 'test' && {
    path: path.resolve(process.cwd(), '.env.test'),
  }

  try {
    return dotenv.config(testOptions)
  } catch (err) {
    console.log(err, 'Missing or wrong env files')
  }
}

module.exports = { loadEnvs }
Enter fullscreen mode Exit fullscreen mode
  • The second file is used to load the appropriate environment variables and run Jest with arguments specified in package.json:
const { loadEnvs } = require('./loadEnvs')

loadEnvs('test')

const argv = process.argv.slice(2)

const jest = require('jest')

jest.run(argv)
Enter fullscreen mode Exit fullscreen mode
  • Finally, I updated the test commands in package.json to align with these changes.
const { loadEnvs } = require('./loadEnvs')

loadEnvs('test')

const argv = process.argv.slice(2)

const jest = require('jest')

jest.run(argv)
Enter fullscreen mode Exit fullscreen mode

Results

Overall the migration took me around 30 minutes, which is quite fast in my opinion - even fact that my app is rather small one.
The docs are great I have easily found, what I needed, big shoutout to the RSBuild Team ❀️

The performance improvements with RSBuild were huge:

  • Local build time: Reduced to about 0.3 seconds πŸ”₯.
  • GitHub CI: Reduced to about 0.8 seconds, which is incredibly fast πŸ”₯.
  • Local development server readiness: Around 0.25 seconds.

RSBuild took 0.8s to build project on CI

In contrast, with CRA:

  • Local build time: Typically 7 to 9 seconds.
  • GitHub CI: Around 26 seconds.
  • Local development server readiness: Between 3 to 5 seconds.

CRA took 26 seconds to build project on CI

Other migration cases

I also explored other developers' experiences with migrating to RSBuild, as shared on Twitter:

Top comments (1)

Collapse
 
upride profile image
Upride Network

Hello
I need your help on how to use good seo changes in my react site:
upride.in