Skip to the solution
MediumFrontend8 min read

How do you enable and evaluate the React Compiler in Next.js 16?

497 views

The problem

Question presented to candidate: "Our team spends a lot of review time arguing about useMemo and useCallback. Next.js 16 says the React Compiler is stable. How would you turn it on, and how would you decide, with evidence, whether it is worth keeping?"

What a strong answer should cover:

  • The React Compiler is a build-time tool that memoizes components and hooks automatically, so values and JSX are only recomputed when their inputs change.
  • Enable it with top-level reactCompiler: true (stable since 16.0, not on by default) plus babel-plugin-react-compiler; 16.3 added experimental.turbopackRustReactCompiler, a native Rust port that needs no Babel plugin.
  • Options: compilationMode: 'annotation' with "use memo" to opt in gradually, and "use no memo" to opt a component out.
  • Evaluate with numbers: render counts (React DevTools Profiler), interaction timings, and build time, before and after; the compiler adds build cost.
  • It only optimises code that follows the Rules of React; code that mutates props or reads refs during render is skipped, so the lint rules matter.

Clarifying questions expected:

  • "Where are the slow interactions today?" β€” the compiler fixes re-render waste, not slow data or large bundles.
  • "Do we have a lot of manual memoization or code that breaks the Rules of React?"

Code / implementation expected: Yes β€” the config, the install command, and a before/after render measurement.

  • nextjs
  • react-compiler
  • performance
  • next-16

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 9 sections

Read the code

next.config.ts: Babel implementation (stable)
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactCompiler: true, // also: npm install -D babel-plugin-react-compiler
};

export default nextConfig;
next.config.ts: Rust implementation (16.3+, experimental)
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactCompiler: true,
  experimental: {
    turbopackRustReactCompiler: true, // no babel-plugin-react-compiler needed, Turbopack only
  },
};

export default nextConfig;
The lab component used to count renders
"use client";
import { useState } from "react";

declare global {
  interface Window { __renders?: Record<string, number> }
}
function track(name: string) {
  if (typeof window !== "undefined") {
    window.__renders ??= {};
    window.__renders[name] = (window.__renders[name] ?? 0) + 1;
  }
}

function Price({ amount }: { amount: number }) {
  track("Price");
  return <p>Price: {amount.toFixed(2)}</p>;
}

function Optout({ amount }: { amount: number }) {
  "use no memo";
  track("Optout");
  return <p>Opted out: {amount}</p>;
}

export function Counter() {
  const [count, setCount] = useState(0);
  track("Counter");
  return (
    <div>
      <button id="inc" onClick={() => setCount(count + 1)}>clicked {count}</button>
      <Price amount={42} />
      <Optout amount={7} />
    </div>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 74 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

What are the special files in the Next.js App Router (page, layout, loading, error)?

Continue