diff --git a/apps/web/REACT_COMPILER.md b/apps/web/REACT_COMPILER.md new file mode 100644 index 00000000..945160a7 --- /dev/null +++ b/apps/web/REACT_COMPILER.md @@ -0,0 +1,24 @@ +# React Compiler rollout + +## Current setup + +- React Compiler is wired through top-level `reactCompiler` in `next.config.mjs`. +- The web app runs on React 19 and Next.js 16, so compiled output can use React's built-in compiler runtime. +- `react-compiler-runtime` is not installed because it is only needed when targeting React 17 or 18. +- The compiler runs in `compilationMode: "annotation"` so only components or hooks with `"use memo"` are compiled. +- `ChannelBadge` is the first annotated component. It is intentionally small and presentational to keep the first rollout low risk. + +## Rollout notes + +- A custom Babel config is intentionally not used because it disables SWC and conflicts with `next/font` in this Next.js app. +- Keep `babel-plugin-react-compiler` aligned with the React Compiler rollout notes when upgrading Next or React. +- Build time should be watched before widening compiler coverage. +- Do not switch to full compilation until the app has a React Compiler lint/audit path. The current repo uses Biome instead of ESLint, so `eslint-plugin-react-hooks` `recommended-latest` is a follow-up decision rather than part of this first slice. +- For any component that behaves incorrectly after annotation, remove `"use memo"` or add `"use no memo"` while investigating. +- Re-check the required `babel-plugin-react-compiler` version whenever Next or React is upgraded. +- When verifying compiled output on React 19, look for `react/compiler-runtime` rather than `react-compiler-runtime`. + +## Verification + +- Run `pnpm --filter @solid-connect/web build` and confirm the compiled server/client output references `react/compiler-runtime`. +- Run `pnpm --filter @solid-connect/web ci:check` before merging. diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 6a940991..e554ef50 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -22,6 +22,9 @@ const imageRemotePatterns = [ /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ["@solid-connect/ai-inspector"], + reactCompiler: { + compilationMode: "annotation", + }, turbopack: { rules: { "*.svg": { diff --git a/apps/web/package.json b/apps/web/package.json index 56481ee3..228e7780 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -56,6 +56,7 @@ "@types/react": "19.2.15", "@types/react-dom": "19.2.3", "autoprefixer": "^10.4.20", + "babel-plugin-react-compiler": "1.0.0", "critters": "^0.0.23", "postcss": "^8.4.45", "tailwindcss": "^3.4.10", diff --git a/apps/web/src/components/ui/ChannelBadge.tsx b/apps/web/src/components/ui/ChannelBadge.tsx index 55fc978a..376204e3 100644 --- a/apps/web/src/components/ui/ChannelBadge.tsx +++ b/apps/web/src/components/ui/ChannelBadge.tsx @@ -6,6 +6,8 @@ interface ChannelBadgeProps { } const ChannelBadge = ({ channelType, text }: ChannelBadgeProps) => { + "use memo"; + return (