fix: resolve webpack module resolution error with wrapper component
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
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Release Sidebar Wrapper
|
||||||
|
*
|
||||||
|
* Simple wrapper to avoid webpack module resolution issues
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ReleaseSidebar } from './release-sidebar'
|
||||||
|
import type { ReleaseNote, GroupMetadata, CategoryMetadata } from '@/lib/mdx/releases'
|
||||||
|
|
||||||
|
interface ReleaseSidebarWrapperProps {
|
||||||
|
releases: ReleaseNote[]
|
||||||
|
metadata: {
|
||||||
|
groups: GroupMetadata[]
|
||||||
|
categories: CategoryMetadata[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ReleaseSidebarWrapper(props: ReleaseSidebarWrapperProps) {
|
||||||
|
return <ReleaseSidebar {...props} />
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import { getAllReleases, getCategoryMetadata } from '@/lib/mdx/releases'
|
import { getAllReleases, getCategoryMetadata } from '@/lib/mdx/releases'
|
||||||
import { ReleaseSidebar } from './components/release-sidebar'
|
import ReleaseSidebar from './components/release-sidebar-wrapper'
|
||||||
|
|
||||||
interface ReleasesLayoutProps {
|
interface ReleasesLayoutProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
|
|||||||
255
docs/troubleshooting/webpack-module-resolution-error.md
Normal file
255
docs/troubleshooting/webpack-module-resolution-error.md
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
# 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?
|
||||||
|
|
||||||
|
1. **Server Component** (bijv. `layout.tsx`) importeert een **Client Component** (met `'use client'` directive)
|
||||||
|
2. Webpack bundelt de Client Component in een aparte chunk voor client-side hydration
|
||||||
|
3. Next.js maakt een proxy module op de Server/Client boundary
|
||||||
|
4. Bij het laden van de webpack chunk verwacht de loader een functie export
|
||||||
|
5. Door timing/caching issues is de export soms `undefined`
|
||||||
|
6. Dit geeft: `TypeError: Cannot read properties of undefined (reading 'call')`
|
||||||
|
|
||||||
|
## Wanneer treedt dit op?
|
||||||
|
|
||||||
|
### Situaties die dit veroorzaken:
|
||||||
|
|
||||||
|
1. **Direct import van Client Component in Server Component**
|
||||||
|
```tsx
|
||||||
|
// layout.tsx (Server Component)
|
||||||
|
import { ClientComponent } from './client-component' // ❌ PROBLEEM
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Named exports met 'use client'**
|
||||||
|
```tsx
|
||||||
|
// client-component.tsx
|
||||||
|
'use client'
|
||||||
|
export function ClientComponent() { ... } // ❌ Kan problemen geven
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Webpack caching issues** na HMR (Hot Module Reload)
|
||||||
|
|
||||||
|
4. **Type imports die conflicteren**
|
||||||
|
```tsx
|
||||||
|
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:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 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:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 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: false` gebruiken in Server Components
|
||||||
|
- Loading state issues
|
||||||
|
- Niet geschikt voor kritieke UI componenten
|
||||||
|
|
||||||
|
### Optie 4: Clean Cache en Rebuild
|
||||||
|
|
||||||
|
Soms is het gewoon cache corruptie:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf .next node_modules
|
||||||
|
pnpm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Preventie: Best Practices
|
||||||
|
|
||||||
|
### 1. Gebruik default exports voor Client Components
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 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
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// ✅ 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf .next
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Check webpack chunks
|
||||||
|
|
||||||
|
Als de error blijft terugkomen, check webpack output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In terminal met dev server
|
||||||
|
# Kijk naar compile output voor errors
|
||||||
|
```
|
||||||
|
|
||||||
|
## Specifieke Case: Release Sidebar
|
||||||
|
|
||||||
|
**Probleem:**
|
||||||
|
- `app/(marketing)/releases/layout.tsx` (Server) importeerde direct `ReleaseSidebar` (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:**
|
||||||
|
```tsx
|
||||||
|
// 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:**
|
||||||
|
1. Default exports voor Client Components
|
||||||
|
2. Wrappers voor Server → Client imports in layouts
|
||||||
|
3. Clean cache bij persistente problemen
|
||||||
|
4. Vermijd mixed type/component imports
|
||||||
Reference in New Issue
Block a user