# How React Compiler Memoization Works in Instatic: Configuration and Exceptions

> Discover how Instatic leverages React Compiler for automatic memoization and explore its three essential exceptions for optimizing components and functions.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: internals
- Published: 2026-07-29

---

**Instatic enables React Compiler via Vite's Babel configuration to automatically memoize components and functions, while strictly limiting manual memoization to three specific exceptions: stabilizing callbacks for hook dependencies, optimizing critical list items, and escaping the compiler for unanalyzable code blocks.**

The Instatic repository leverages the React Compiler to eliminate manual memoization overhead across its entire React application. By integrating the compiler into the build pipeline through Vite, the project automatically optimizes component re-renders without requiring `useMemo`, `useCallback`, or `React.memo` in standard code. Understanding how this automatic React Compiler memoization functions—and where it requires human intervention—is essential for contributing to the codebase.

## How the React Compiler Is Configured in Instatic

Instatic enables the compiler project-wide through the Babel preset defined in [`vite.config.ts`](https://github.com/CoreBunch/Instatic/blob/main/vite.config.ts). The configuration imports `reactCompilerPreset` from `@babel/preset-react-compiler` and appends it to the Babel presets array:

```ts
import { reactCompilerPreset } from '@babel/preset-react-compiler'
export default defineConfig({
  // …
  plugins: [
    // other Vite plugins …
  ],
  // Babel is wired via Vite’s `babel` option
  babel: {
    presets: [reactCompilerPreset()],
  },
})

```

This setup instructs Babel to process every component with the React Compiler, which performs **static memoization** automatically. The compiler analyzes dependency graphs at build time to determine when values, functions, and component outputs can be safely cached between renders.

## Automatic Memoization and the "No Manual Memoization" Rule

When the React Compiler is active, it generates optimal memoization automatically for all functions, values, and components. Consequently, the Instatic codebase follows a strict **"no manual memoization"** guideline—developers must avoid `useMemo`, `useCallback`, and `React.memo` unless they fall under one of the documented exceptions. This rule reduces code noise and prevents redundant optimization efforts that the compiler already handles.

Standard components in `src/ui/components/**` rely entirely on this automatic behavior:

```tsx
// src/ui/components/Button/Button.tsx
export function Button({ children, onClick }: Props) {
  // No useCallback / useMemo needed – the compiler will memoize `onClick`
  return <button onClick={onClick}>{children}</button>
}

```

## The Three Exceptions to Automatic Memoization

The [`docs/reference/react-compiler.md`](https://github.com/CoreBunch/Instatic/blob/main/docs/reference/react-compiler.md) file documents three specific scenarios where manual memoization remains necessary.

### Stable Function Identity for Hook Dependencies

When a function is listed in a `useEffect` dependency array (or similar hook), you must wrap it with `useCallback` to satisfy the `react-hooks/exhaustive-deps` linter rule, even though the compiler handles the actual memoization. This ensures the linter correctly tracks dependencies without flagging missing entries.

```tsx
export function AutoSave({ save }: { save: () => Promise<void> }) {
  const stableSave = useCallback(() => {
    void save()
  }, [save])               // <- required for useEffect deps
  
  useEffect(() => {
    const id = setInterval(stableSave, 5000)
    return () => clearInterval(id)
  }, [stableSave])
  
  return null
}

```

### Critical List-Rendered Components

Components rendered inside large lists may be wrapped with `React.memo` to skip unnecessary re-renders, but only after rigorous performance validation proves the optimization necessary. This exception targets heavy components like those rendering complex SVGs or costly calculations where the compiler's automatic memoization might not provide sufficient isolation at the list item level.

```tsx
// ListItem renders a complex SVG; memoised to avoid re‑renders
export const ListItem = React.memo(function ListItem({ item }: { item: Item }) {
  return <div>{item.title}</div>
})

```

### Compiler Escape-Hatch for Unanalyzable Code

If the compiler cannot process a function due to dynamic code generation or other edge cases, developers must disable the compiler for that specific block using the `/* @react-compiler-disable */` directive. In these isolated blocks, manual memoization can be retained as needed since the compiler is not managing the component.

```tsx
/* @react-compiler-disable */
export function UnsafeDynamicFunction({ fn }: { fn: Function }) {
  // Runtime‑generated code that the compiler cannot analyze
  return <button onClick={() => fn()}>Run</button>
}

```

## Enforcement Through Linting

The project enforces these rules through [`eslint.config.js`](https://github.com/CoreBunch/Instatic/blob/main/eslint.config.js) and [`react-doctor.config.json`](https://github.com/CoreBunch/Instatic/blob/main/react-doctor.config.json), which flag violations of the "no manual memoization" policy. These configurations ensure developers do not accidentally introduce `useMemo` or `useCallback` in standard components where the React Compiler already provides optimization.

## Summary

- Instatic enables React Compiler memoization globally via the `reactCompilerPreset` in [`vite.config.ts`](https://github.com/CoreBunch/Instatic/blob/main/vite.config.ts), which processes all components through Babel at build time.
- The codebase prohibits manual memoization (`useMemo`, `useCallback`, `React.memo`) because the compiler handles optimization automatically.
- Three exceptions allow manual memoization: stabilizing callbacks for hook dependency arrays, memoizing performance-critical list items after validation, and using the `/* @react-compiler-disable */` escape-hatch for code the compiler cannot analyze.
- Linting rules in [`eslint.config.js`](https://github.com/CoreBunch/Instatic/blob/main/eslint.config.js) enforce the manual memoization restrictions across the `src/ui/components/**` directory.

## Frequently Asked Questions

### Can I use useMemo and useCallback in Instatic?

Generally, no. According to the Instatic source code, you should avoid `useMemo` and `useCallback` in standard components because the React Compiler automatically memoizes values and functions. The only permitted uses are the three documented exceptions: stabilizing functions for hook dependencies, optimizing validated list items, and code blocks where the compiler is explicitly disabled.

### How do I disable the React Compiler for a specific component?

Use the `/* @react-compiler-disable */` comment immediately before the function definition. This escape-hatch tells Babel to skip compilation for that specific block, allowing you to implement manual memoization strategies for code that the compiler cannot statically analyze, such as runtime-generated functions.

### Where is the React Compiler configured in the Instatic codebase?

The compiler is configured in [`vite.config.ts`](https://github.com/CoreBunch/Instatic/blob/main/vite.config.ts) at the repository root. The file imports `reactCompilerPreset` from `@babel/preset-react-compiler` and includes it in the Babel presets array, ensuring all components in the project are processed automatically without requiring individual configuration.

### Why does Instatic require useCallback for hook dependencies despite the compiler?

While the React Compiler handles the actual memoization, the `react-hooks/exhaustive-deps` ESLint rule cannot detect that the compiler will stabilize function identities. Wrapping callbacks with `useCallback` satisfies the linter's requirement that all dependencies be explicitly declared in hook arrays, preventing false positive linting errors while maintaining correct dependency tracking.