| 108 | 108 | | |
| 109 | 109 | | Occasionally, a library might bundle its own copy of React instead of importing it as a peer dependency. This can cause the "multiple React instances" problem — hooks errors (`Invalid hook call`) or context not being shared. However, `@lazarv/react-server` already deduplicates `react` and `react-dom` automatically, so most of these cases are handled for you without any extra configuration. |
| 110 | 110 | | |
| 111 | + | <Link name="react-compiler"> |
| 112 | + | ## React Compiler |
| 113 | + | </Link> |
| 114 | + | |
| 115 | + | [React Compiler](https://react.dev/learn/react-compiler) is an opt-in Babel plugin that automatically memoizes React components and hooks. It removes most of the manual `useMemo`, `useCallback`, and `React.memo` boilerplate by analyzing your code at build time and emitting `useMemoCache` calls for the values that need to be cached. |
| 116 | + | |
| 117 | + | Because `@lazarv/react-server` already uses `@vitejs/plugin-react` internally to apply the React Babel transform, enabling React Compiler is a matter of providing your own `@vitejs/plugin-react` instance with `babel-plugin-react-compiler` configured. When the runtime detects a user-supplied `vite:react` plugin in your config, it uses yours in place of the built-in one — so the runtime's React aliasing, JSX transform, and Fast Refresh continue to work exactly as before. |
| 118 | + | |
| 119 | + | ### Install |
| 120 | + | |
| 121 | + | ```sh |
| 122 | + | pnpm add -D @vitejs/plugin-react babel-plugin-react-compiler |
| 123 | + | ``` |
| 124 | + | |
| 125 | + | You do **not** need to install `react` or `react-dom` — see [No React in your package.json](#no-react-in-your-package-json). |
| 126 | + | |
| 127 | + | ### Configure |
| 128 | + | |
| 129 | + | Add `@vitejs/plugin-react` with `babel-plugin-react-compiler` to your `react-server.config.mjs`: |
| 130 | + | |
| 131 | + | ```js filename="./react-server.config.mjs" |
| 132 | + | import react from "@vitejs/plugin-react"; |
| 133 | + | |
| 134 | + | export default { |
| 135 | + | plugins: [ |
| 136 | + | react({ |
| 137 | + | babel: { |
| 138 | + | plugins: [ |
| 139 | + | [ |
| 140 | + | "babel-plugin-react-compiler", |
| 141 | + | { |
| 142 | + | target: "19", |
| 143 | + | }, |
| 144 | + | ], |
| 145 | + | ], |
| 146 | + | }, |
| 147 | + | }), |
| 148 | + | ], |
| 149 | + | }; |
| 150 | + | ``` |
| 151 | + | |
| 152 | + | The `target: "19"` option tells React Compiler to emit calls to React 19's built-in `useMemoCache` hook, which the React build that ships with `@lazarv/react-server` supports natively. No `react-compiler-runtime` polyfill is required. |
| 153 | + | |
| 154 | + | ### Verify it is running |
| 155 | + | |
| 156 | + | After a build (`react-server build`), inspect a compiled client component bundle in `.react-server/client/`. Compiled components contain a call like `c(N)` (the `useMemoCache` cache) and `Symbol.for("react.memo_cache_sentinel")` slot initializers. If you see those, the compiler is active. |
| 157 | + | |
| 158 | + | ### Compilation modes |
| 159 | + | |
| 160 | + | By default, React Compiler runs in `infer` mode and tries to memoize every component it can prove safe. To opt in selectively instead, set `compilationMode: "annotation"` and add a `"use memo"` directive to the components or hooks you want compiled: |
| 161 | + | |
| 162 | + | ```js filename="./react-server.config.mjs" |
| 163 | + | react({ |
| 164 | + | babel: { |
| 165 | + | plugins: [ |
| 166 | + | [ |
| 167 | + | "babel-plugin-react-compiler", |
| 168 | + | { |
| 169 | + | target: "19", |
| 170 | + | compilationMode: "annotation", |
| 171 | + | }, |
| 172 | + | ], |
| 173 | + | ], |
| 174 | + | }, |
| 175 | + | }), |
| 176 | + | ``` |
| 177 | + | |
| 178 | + | ```jsx filename="./Chart.jsx" |
| 179 | + | "use client"; |
| 180 | + | |
| 181 | + | function Chart({ data }) { |
| 182 | + | "use memo"; |
| 183 | + | // …only this component is compiled. |
| 184 | + | } |
| 185 | + | ``` |
| 186 | + | |
| 187 | + | ### Server vs. client components |
| 188 | + | |
| 189 | + | The Babel transform runs across all three environments (`rsc`, `ssr`, and `client`), so React Compiler may compile both server and client components. Only client components benefit from re-render memoization in the browser; server components are still useful to compile because the same transform runs during SSR. If a particular file should not be compiled, exclude it via the standard `babel-plugin-react-compiler` options (`sources` filter or `"use no memo"` directive). |
| 190 | + | |
| 191 | + | For server functions (`"use server"`) the compiler is a no-op — they are not React components and the compiler ignores them by structure. |
| 192 | + | |
| 193 | + | ### Example |
| 194 | + | |
| 195 | + | A complete working setup is available in the [`react-compiler` example](https://github.com/lazarv/react-server/tree/main/examples/react-compiler). |
| 196 | + | |
| 111 | 197 | | <Link name="typescript-types"> |
| 112 | 198 | | ## TypeScript types |
| 113 | 199 | | </Link> |