Optimizing Three.js in Next.js 15 (App Router)
To build a high-performance 3D interactive restaurant menu or any complex WebGL scene, you should focus on these three pillars:
1. Use React Three Fiber (R3F) with Canvas Persistence
While vanilla Three.js is powerful, React Three Fiber is the standard for Next.js. To prevent the scene from unmounting or re-rendering during route changes:
- Wrap your
Canvasin a Persistent Layout (e.g.,template.tsxor a globallayout.tsx). - Use Shared State (like Zustand or Valtio) to control 3D elements based on the current route without re-creating the entire WebGL context.
2. Efficient Asset Loading (GLTF/GLB)
Loading heavy models can freeze the UI. Use these techniques:
useGLTFwith Suspense: Leverage React Suspense to show a 2D loading placeholder while the 3D assets are being fetched.- Draco Compression: Always compress your
.glbmodels using Draco. It significantly reduces file size (often by 70-90%). - Preloading: Use
useGLTF.preload('/model.glb')in your main entry point to start downloading the assets before the user even navigates to the 3D section.
3. Performance & Rendering Tweak
next/dynamic: Import your 3D components usingdynamic(() => import('./Scene'), { ssr: false }). This ensures that heavy WebGL code is only loaded on the client side.- On-Demand Rendering: By default, Three.js renders at 60fps even if nothing moves. Set
frameloop="demand"in your<Canvas>to only render frames when a change occurs, saving battery and CPU.
Read more...