From e2a4fc68b7ba5616d6f18f6f6301cc1238da287f Mon Sep 17 00:00:00 2001 From: colinislit Date: Wed, 19 Nov 2025 21:41:10 +0100 Subject: [PATCH] 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 --- .../components/release-sidebar-wrapper.tsx | 20 ++ app/(marketing)/releases/layout.tsx | 2 +- .../webpack-module-resolution-error.md | 255 ++++++++++++++++++ 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 app/(marketing)/releases/components/release-sidebar-wrapper.tsx create mode 100644 docs/troubleshooting/webpack-module-resolution-error.md diff --git a/app/(marketing)/releases/components/release-sidebar-wrapper.tsx b/app/(marketing)/releases/components/release-sidebar-wrapper.tsx new file mode 100644 index 0000000..4e11c66 --- /dev/null +++ b/app/(marketing)/releases/components/release-sidebar-wrapper.tsx @@ -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 +} diff --git a/app/(marketing)/releases/layout.tsx b/app/(marketing)/releases/layout.tsx index 7ced41a..4b0df34 100644 --- a/app/(marketing)/releases/layout.tsx +++ b/app/(marketing)/releases/layout.tsx @@ -6,7 +6,7 @@ import type { ReactNode } from 'react' import { getAllReleases, getCategoryMetadata } from '@/lib/mdx/releases' -import { ReleaseSidebar } from './components/release-sidebar' +import ReleaseSidebar from './components/release-sidebar-wrapper' interface ReleasesLayoutProps { children: ReactNode diff --git a/docs/troubleshooting/webpack-module-resolution-error.md b/docs/troubleshooting/webpack-module-resolution-error.md new file mode 100644 index 0000000..c00d67c --- /dev/null +++ b/docs/troubleshooting/webpack-module-resolution-error.md @@ -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 +} + +// 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 +} +``` + +## 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