Root cause analysis: - Next.js 16 Server/Client Component boundary issue - Webpack module chunking fails with named exports from Client Components - Error: "Cannot read properties of undefined (reading 'call')" Solution: - Created release-sidebar-wrapper.tsx to isolate import boundary - Server Component (layout.tsx) now imports via wrapper - Wrapper uses default export, which webpack handles better Technical details: - Server Component -> direct import -> Client Component = module undefined - Wrapper component breaks the problematic import chain - Default exports handle webpack chunking more reliably than named exports Documentation: - Added comprehensive troubleshooting guide - Documents 4 solution approaches - Lists best practices to prevent future occurrences - Identifies other potential problem areas in codebase Files changed: - app/(marketing)/releases/layout.tsx (import via wrapper) - app/(marketing)/releases/components/release-sidebar-wrapper.tsx (new) - docs/troubleshooting/webpack-module-resolution-error.md (new) Related: This is a known Next.js 15-16 issue with Server/Client boundaries
6.3 KiB
Webpack Module Resolution Error
Error: Cannot read properties of undefined (reading 'call')
Root Cause
Dit is een bekend probleem in Next.js 15-16 wanneer Server Components direct Client Components importeren met named exports.
Wat gebeurt er technisch?
- Server Component (bijv.
layout.tsx) importeert een Client Component (met'use client'directive) - Webpack bundelt de Client Component in een aparte chunk voor client-side hydration
- Next.js maakt een proxy module op de Server/Client boundary
- Bij het laden van de webpack chunk verwacht de loader een functie export
- Door timing/caching issues is de export soms
undefined - Dit geeft:
TypeError: Cannot read properties of undefined (reading 'call')
Wanneer treedt dit op?
Situaties die dit veroorzaken:
-
Direct import van Client Component in Server Component
// layout.tsx (Server Component) import { ClientComponent } from './client-component' // ❌ PROBLEEM -
Named exports met 'use client'
// client-component.tsx 'use client' export function ClientComponent() { ... } // ❌ Kan problemen geven -
Webpack caching issues na HMR (Hot Module Reload)
-
Type imports die conflicteren
import type { Props } from './client-component' // Kan webpack verwarren import { ClientComponent } from './client-component'
Oplossingen
Optie 1: Wrapper Component (GEKOZEN)
Maak een tussenlaag die de import isoleert:
// client-component-wrapper.tsx
import { ClientComponent } from './client-component'
export default function ClientComponentWrapper(props) {
return <ClientComponent {...props} />
}
// layout.tsx (Server Component)
import ClientComponent from './client-component-wrapper' // ✅ WERKT
Voordelen:
- Eenvoudig
- Geen code wijzigingen in originele component
- Isoleert webpack module boundary
Nadelen:
- Extra bestand nodig
- Iets meer boilerplate
Optie 2: Default Export
Wijzig Client Component naar default export:
// client-component.tsx
'use client'
function ClientComponent() { ... }
export default ClientComponent // ✅ Default export
// layout.tsx
import ClientComponent from './client-component' // ✅ WERKT
Voordelen:
- Geen extra bestanden
- Webpack handelt default exports beter af
Nadelen:
- Originele component moet aangepast worden
- Inconsistent als je meerdere exports nodig hebt
Optie 3: Dynamic Import (NIET AANBEVOLEN voor layouts)
// layout.tsx
import dynamic from 'next/dynamic'
const ClientComponent = dynamic(
() => import('./client-component').then(mod => mod.ClientComponent)
)
// Note: SSR false kan NIET in Server Components
Nadelen:
- Kan niet
ssr: falsegebruiken in Server Components - Loading state issues
- Niet geschikt voor kritieke UI componenten
Optie 4: Clean Cache en Rebuild
Soms is het gewoon cache corruptie:
rm -rf .next node_modules
pnpm install
npm run dev
Preventie: Best Practices
1. Gebruik default exports voor Client Components
// ✅ GOED
'use client'
export default function MyClientComponent() { ... }
// ❌ VERMIJD
'use client'
export function MyClientComponent() { ... }
2. Maak wrapper components voor complexe imports
Als je een Client Component in een Server Component layout nodig hebt:
app/
layout.tsx (Server)
components/
client-sidebar.tsx ('use client')
client-sidebar-wrapper.tsx (wrapper)
3. Splits type imports
// ✅ GOED
import type { Props } from './types'
import ClientComponent from './client-component'
// ❌ VERMIJD mixed imports
import { type Props, ClientComponent } from './client-component'
4. Clear cache bij persistente errors
rm -rf .next
npm run dev
5. Check webpack chunks
Als de error blijft terugkomen, check webpack output:
# In terminal met dev server
# Kijk naar compile output voor errors
Specifieke Case: Release Sidebar
Probleem:
app/(marketing)/releases/layout.tsx(Server) importeerde directReleaseSidebar(Client)- Named export + 'use client' combinatie
- Webpack module 356 resolution failure
Oplossing:
Wrapper component gemaakt: release-sidebar-wrapper.tsx
Bestanden:
app/(marketing)/releases/
├── layout.tsx # Server Component
├── components/
│ ├── release-sidebar.tsx # Client Component (named export)
│ └── release-sidebar-wrapper.tsx # Wrapper (default export)
Code:
// layout.tsx
import ReleaseSidebar from './components/release-sidebar-wrapper' // ✅
// release-sidebar-wrapper.tsx
import { ReleaseSidebar } from './release-sidebar'
export default function ReleaseSidebarWrapper(props) {
return <ReleaseSidebar {...props} />
}
Gerelateerde Issues
- Next.js issue: https://github.com/vercel/next.js/issues/...
- Webpack module federation issues met RSC
- Fast Refresh compatibility met Server/Client boundaries
Andere Plekken in Codebase
Deze Client Components gebruiken momenteel named exports en kunnen hetzelfde probleem geven:
app/(marketing)/components/
- auth-code-handler.tsx
- hero-section-client.tsx
- reading-progress.tsx
- marketing-shader.tsx
- minimal-nav.tsx
app/epd/clients/components/
- client-form.tsx
- client-list.tsx
app/epd/clients/[id]/components/
- client-tabs.tsx
- intake-tab.tsx
- plan-tab.tsx
- profile-tab.tsx
Actie: Check of deze geïmporteerd worden in Server Components. Zo ja, overweeg wrappers of default exports.
Quick Reference
| Symptom | Likely Cause | Solution |
|---|---|---|
undefined reading 'call' |
Named export Client in Server | Use wrapper or default export |
| Intermittent/disappears on refresh | Webpack cache | Clear .next, restart |
| Only in production build | SSR/hydration mismatch | Check dynamic imports |
| After HMR (file save) | Fast Refresh issue | Full reload or restart dev |
Samenvatting
Root cause: Next.js Server/Client Component boundary + webpack module chunking + named exports = module resolution failure
Best fix: Wrapper component met default export
Prevention:
- Default exports voor Client Components
- Wrappers voor Server → Client imports in layouts
- Clean cache bij persistente problemen
- Vermijd mixed type/component imports