Beginner's Guide to Using the React Compiler

Not a Step-by-Step Guide to the React Compiler

Beginner's Guide to Using the React Compiler

There have been chats about the React compiler for quite some time now, and the team at React Conf'24 just gave a demo of it, and wow, am I excited! I totally recommend you check out the talks yourself, dropping an easter egg here : they built a workable compiler in just 20 minutes!

So what really gets me excited about the React Compiler?

Well, I'm just an average developer like most of us out there (though many won't admit it). I love it when things get simpler and easier to handle without losing the essence of building something by hand. That's where the real magic happens. It's like adding paddle shifters to a car—it makes driving smoother but doesn't turn it into a self-driving car. You still get the joy of driving.

Okay, that might have been a bit too philosophical for a "Tech Blog."

And now for no reason at all:

Ok but why is this a thing : r/memes

Tldr; You no longer need to use useMemo, React.Memo, or useCallback to optimise your code and do manual memoization. The React compiler handles it for you, as long as you follow the "Rules of React".

If it detects breakages of the rules, it will automatically skip over just those components or hooks.

Should you🦁 try out the compiler?

Not really, Builds are for losers. top coders prefer code written in straight up assembly. Me is not a top coder, so I tried it anyway !

The few obvious wins for me would be :

  • Improved Code Quality: By automating optimisations, React Compiler reduces the need for developers to write and maintain complex performance-related code. This leads to cleaner and more maintainable codebases.

  • Faster Development Times: With React Compiler handling optimisations, developers can focus on core functionalities rather than spending time on performance tweaks. This can significantly accelerate the development process.

It's important to remember that React Compiler is still under development and might not be entirely production-ready.

In the next sections of the blog I will try to guide you to build a basic POC to test the React Compiler in action.


Testing React Compiler with Vite and Babel Plugin

Let's explore how to test React Compiler using Vite.

These instructions are focused on installing React Compiler in new projects. If you want to configure it for your existing apps, please check out the official documentation ➡️ 💾.

  1. Setting Up the Project:

    • Begin by creating a new React project using your preferred method (e.g., npm create vite@latest).

    • Install and setup vite⚡️

    npm create vite@latest
💡
Common Issue:

(0 , _c) is not a function error
This occurs during JavaScript module evaluation when you are not using React 19 Beta and up. To fix this, upgrade your app to React 19 Beta first.

  1. Checking compatibility:
  • Prior to installing the compiler, you can first check to see if your codebase is compatible:

      npx react-compiler-healthcheck
    

    This script will:

    • Check how many components can be successfully optimized: higher is better

    • Check for <StrictMode> usage: having this enabled and followed means a higher chance that the Rulesof React are followed

    • Check for incompatible library usage: known libraries that are incompatible with the compiler.

As an example:

    Successfully compiled 8 out of 9 components.
    StrictMode usage not found.
    Found no usage of incompatible libraries.
  1. Usage with Vite:

    If you use Vite, you can add the plugin to vite-plugin-react:

     // vite.config.js
     const ReactCompilerConfig = { /* ... */ };
    
     export default defineConfig(() => {
       return {
         plugins: [
           react({
             babel: {
               plugins: [
                 ["babel-plugin-react-compiler", ReactCompilerConfig],
               ],
             },
           }),
         ],
         // ...
       };
     });
    

Testing with a Slow Component:

import React, { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

//block synchronously for 2 seconds
function blockSync(ms){
  const start = Date.now();
  let now = start;
  while (now-start < ms){
    now = Date.now();
  }
}

function SlowComponent(){
  blockSync(2000);
  return <div>This is a slow component</div>;
}

const MemoSlow = React.memo(SlowComponent);

function App() {
  const [count, setCount] = useState(0)

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          {`Count is ${count}`}
        </button>
        <br/><br/><br/>
        <SlowComponent/>
        {/* <MemoSlow/> */}
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App;

The blockSync function is meant to replicate the load times when we use the compiler and don't use the usually method of wrapping the slow component under React.memo().


Results:

For no reason at all, Episode 2 (Netflix drumrolls)

Image

Without Memoization hooks and No React Compiler
Comment the ReactCompiler plugin in vite config:

export default defineConfig(() => {
  return {
    plugins: [
      react({
        babel: {
          plugins: [
            // ["babel-plugin-react-compiler", ReactCompilerConfig],
          ],
        },
      }),
    ],
    // ...
  };
});
//vite.config.js

With Memoization hooks and No React Compiler:
Comment the slow component and enable the memoized component:

    // ...
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          {`Count is ${count}`}
        </button>
        <br/><br/><br/>
        {/* <SlowComponent/> */}
        <MemoSlow/>
      </div>
    // ...
//App.jsx

Without Memoization hooks but with React Compiler:
Magic 🪄✨
Uncomment the slow component in app.jsx and the compiler plugin in vite config file. Comment the memorised component:

export default defineConfig(() => {
  return {
    plugins: [
      react({
        babel: {
          plugins: [
            ["babel-plugin-react-compiler", ReactCompilerConfig],
          ],
        },
      }),
    ],
    // ...
  };
});
//vite.config.js
    // ...
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          {`Count is ${count}`}
        </button>
        <br/><br/><br/>
        <SlowComponent/>
        {/* <MemoSlow/> */}
      </div>
    // ...
//App.jsx


Conclusions

React Compiler is a promising and has the potential to streamline React development. By automating performance optimisations, it can improve code quality and development speed.

Self driving cars suck big time anyways !!!