June 28th, 2024

Understanding React Compiler

React's core architecture simplifies development but can lead to performance issues. The React team introduced the React Compiler to automate performance tuning by rewriting code. Transpilers like Babel convert JSX for efficiency. Compilers, transpilers, and optimizers analyze and produce equivalent code. React Compiler enhances functionality using Abstract Syntax Trees, memoization, and hook storage for optimized performance.

Read original articleLink Icon
Understanding React Compiler

React's core architecture simplifies development but can lead to performance issues if functions are expensive. To address this, the React team introduced the React Compiler, automating performance tuning by rewriting code. Transpilers like Babel convert JSX into nested function calls for efficiency. Compilers, transpilers, and optimizers are tools that analyze and produce functionally equivalent code. React Compiler uses Abstract Syntax Trees to generate new React code, enhancing functionality. Understanding React's core architecture involves creating a Virtual DOM and utilizing memoization to cache results of expensive functions. React stores state using hooks, like useState and useReducer, in a linked list structure for efficient data management. React Compiler combines memoization and hook storage to optimize performance. By storing cache on the Fiber tree, React ensures efficient function calls and state management. This approach enhances React's capabilities and aids in maintaining app performance.

Link Icon 14 comments
By @vbezhenar - 5 months
I used to think that React is awesome, but this has gone too far. They just don't care about JavaScript.

1. They introduced hooks which must be called in the same order for every execution. You can't put hook inside `if`. Hooks are based on magic. This is terrible design.

2. They didn't adopt async/await, inventing their own suspend stuff.

3. Now this: they just convert the source language into something else.

The JSX idea is gold: introduce XML-like template syntax into the language to avoid need for foreign template language. Make XML templates valid at startup and even with proper types for TypeScript. This is very important advancement compared to text templates which are used everywhere else.

The stateless render function is good. Emit desired-state, let framework to reconcile current state to desired state.

But rest of React is not gold.

By @a_wild_dandan - 5 months
I love React. It feels foundational somehow. It's also vindicating after toiling for years on bloated frameworks. Declaratively describe your UI, React paints it. That's it. No app state management. No routing. No learning yet another templating system (which inevitably morphs into a shitty programming language). Just full JS(X optional). No grokking convoluted, bespoke abstractions. It's clean, narrowly scoped, and as simple as possible (but not simpler).

Having recently worked on two legacy apps -- one ASP.NET, one Angular -- it made me deeply appreciate React and how far UI tech has come. Phenomenal work from the React team on more optimizations via this compiler. Good article too.

By @whalesalad - 5 months
I haven't used React in about 6 years - used to be pretty heavily involved with it across web and native. These days I truly feel like ecosystem has lost its mind and the developers are just bikeshedding the most esoteric and unhinged choices possible.
By @rixtox - 5 months
I think React would get better developer experience and performance if they adopt language coroutine feature to implement direct style algebraic effect. In fact the React Fiber system is already an implementation of algebraic effect.[1] However, it’s “suspending” a routine by raising an exception. Thus unwinding all the call stack, therefore, it needs to re-run that same routine on resume. This is the core reason why they have a performance issue and why they created the compiler to cache values on reruns.

JavaScript has language level coroutine features like async/await or yield/yield* and we have seen libraries using these features to implement direct style algebraic effect. For example Effect[2] and Effection[3]. You don’t need to memoize things if the language runtime can suspend and resume your functions instead of throwing exceptions and rerun them.

[1]: https://youtu.be/7GcrT0SBSnI

[2]: https://effect.website/

[3]: https://frontside.com/effection/

By @BigJono - 5 months
What am I missing? You gave two examples:

The first is replacing useMemo with some inline code that does the same thing, so, as far as I can tell that literally saves just one function call to useMemo but none of the actual work it does? How could that possibly have a performance impact?

The second is de-inlining (or whatever the proper word is) map(x => foo(x)) to save function definitions on each loop. I don't understand why a "React compiler" would be able to do this if a JS JIT compiler can't, what guarantee does it have that a JS compiler doesn't? This should be done by V8 or not at all.

Even though you have a whole paragraph on the cognitive load of an extra compilation step at the end of your post, which is bang on, IMO you don't even come CLOSE to explaining why this trade off is worth it.

I've been telling people for nine years that React is the best of the declarative DOM libraries because it has a simple line-for-line transform instead of a big complicated compilation step. It looks to me like we're just throwing that all in the bin for absolutely fuck all.

By @Waterluvian - 5 months
The thing I'm struggling with as I read the official documentation and various blogs is exactly how this changes the developer experience. Do I get to remove `React.memo` and `useMemo` and never use them again? Is their use still useful for other cases? What do I have to think about when writing components so that I get this automagical memoization in some cases?
By @willsmith72 - 5 months
I love how we're all talking about state management.

Just use Remix. The database/url is your state.

Messy state management in Client-Side react is a problem of the late 2010s

By @chrsig - 5 months
Slightly tangential question: Where is jsx defined, as a language? are there multiple transpiler implementations? is it standardized at all?
By @robertoandred - 5 months
Not sure what everyone is so upset about. Since when is code optimization a bad thing?
By @TonyAlicea10 - 5 months
I’m the author of this blog post, very cool to have it here.

One thing I didn’t say in the post: I’m very much a fundamentals-first kind of dev. I teach fundamentals in my courses.

I don’t think you should use tools like frameworks or transpilers/compilers without understanding how they work, because debugging is always better when you know what the tool is doing for you, and it makes it easier to use the tool. React is a particularly leaky abstraction that benefits from understanding it under-the-hood.

You need strong fundamentals to understand how things work.

By @gepardi - 5 months
I’ve worked with React, plenty of years. I haven’t had to touch it in months and don’t want to.

Seeing JSX and reading about all the complexity in this post makes me hope I’ll never use React again.

BTW I do like JavaScript.

By @meiraleal - 5 months
For almost 10 years, the core react developers would repeat incessantly: React is a library, not a framework.

In the past 2 or 3 years, they just "gave" up, turned it into the biggest most bloated framework in the frontend area while the official Web APIs in the browsers evolved so much that React is actually completely useless and now it is completely useless with a compiler.

I'm wondering if that was actually the reason they pivoted to this Frankstein? The loss of relevance as a frontend library.

Anyway, I jumped off the bandwagon and don't have a say in this fight anymore. But I'm doing my part advising every Junior Developer to not make the mistake of choosing React today.