nextjs - 💡(How to fix) Fix Turbopack: next/dynamic lazy chunk uses stale module graph after source file changes [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#93292Fetched 2026-04-28 06:23:25
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Error Message

  • Without next/dynamic (static import in Server Component → Client Component → VideoCard), the same edit compiles correctly — the inline function is used and no error occurs.

Fix Action

Fix / Workaround

Discovered while debugging SSR hydration issues. Using next/dynamic with ssr: false in a Client Component (to bypass hydration mismatch from Zustand store state divergence) exposed this chunk compilation bug. The workaround is to use static imports only, which limits the options for SSR hydration control.

Code Example

import { getAdaptiveThumbnailUrl } from "@/lib/canvas/video-utils"

---

"use client"
   import dynamic from "next/dynamic"
   const Hub = dynamic(() => import("./Hub").then(m => ({ default: m.Hub })), { ssr: false })
   export function Loader(props) { return <Hub {...props} /> }

---

// Remove: import { getAdaptiveThumbnailUrl } from "@/lib/canvas/video-utils"
   // Add inline:
   function adaptiveThumbnail(url, width) { /* same logic */ }

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin 23.6.0
  Available memory (MB): 65536
  Available CPU cores: 12
Binaries:
  Node: 24.13.0
  npm: 11.4.1
  pnpm: 10.7.0
Runtime versions:
  React: 19.2.4
  Next.js: 16.1.6
  Turbopack: enabled (default)
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

Private repo — minimal reproduction described below.

To Reproduce

  1. Create a Client Component VideoCard.tsx that imports a function from video-utils.ts:

    import { getAdaptiveThumbnailUrl } from "@/lib/canvas/video-utils"
  2. Create a Client Component wrapper Loader.tsx that uses next/dynamic with ssr: false:

    "use client"
    import dynamic from "next/dynamic"
    const Hub = dynamic(() => import("./Hub").then(m => ({ default: m.Hub })), { ssr: false })
    export function Loader(props) { return <Hub {...props} /> }
  3. Use Loader in a Server Component page.

  4. Start dev server: npx next dev --turbopack

  5. Verify the page works (VideoCard renders thumbnails using getAdaptiveThumbnailUrl).

  6. Edit VideoCard.tsx: replace the import with an inline function:

    // Remove: import { getAdaptiveThumbnailUrl } from "@/lib/canvas/video-utils"
    // Add inline:
    function adaptiveThumbnail(url, width) { /* same logic */ }

    Update the call site from getAdaptiveThumbnailUrl(...) to adaptiveThumbnail(...).

  7. Stop the dev server, run rm -rf .next, restart the dev server.

  8. Result: the lazy-loaded chunk still references getAdaptiveThumbnailUrl from video-utils.ts instead of using the new inline adaptiveThumbnail. The chunk hash (src_1833ede1._.js) does not change despite the source file being different on disk.

Current vs. Expected behavior

Current: Turbopack generates the same chunk hash and content for the next/dynamic lazy chunk even after the source file is edited, rm -rf .next is run, and the dev server is fully restarted. The old import reference causes a runtime TypeError: getAdaptiveThumbnailUrl is not a function.

Expected: After rm -rf .next + server restart, Turbopack should recompile all chunks from the current source files. The lazy chunk should reflect the updated VideoCard.tsx with no reference to the removed import.

Additional context

  • Without next/dynamic (static import in Server Component → Client Component → VideoCard), the same edit compiles correctly — the inline function is used and no error occurs.
  • The bug is specific to the lazy chunk boundary created by next/dynamic with ssr: false.
  • The chunk filename hash (src_1833ede1) is deterministic and unchanged across restarts, suggesting the module graph snapshot used for the lazy chunk ignores the file content changes.
  • Verified source file on disk is correct (head -20 VideoCard.tsx shows the inline function, no old import).

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin 23.6.0
  Available memory (MB): 65536
  Available CPU cores: 12
Binaries:
  Node: 24.13.0
  npm: 11.4.1
  pnpm: 10.7.0
Runtime versions:
  React: 19.2.4
  Next.js: 16.1.6
  Turbopack: enabled (default)

Which area(s) are affected?

Turbopack

Which stage(s) are affected?

next dev (development)

Additional context

Discovered while debugging SSR hydration issues. Using next/dynamic with ssr: false in a Client Component (to bypass hydration mismatch from Zustand store state divergence) exposed this chunk compilation bug. The workaround is to use static imports only, which limits the options for SSR hydration control.

extent analysis

TL;DR

The issue can be resolved by properly handling the cache or module graph snapshot used by Turbopack for lazy chunks created with next/dynamic and ssr: false.

Guidance

  • Verify that the rm -rf .next command is correctly removing all cached files and that there are no other caching mechanisms (like service workers or browser cache) interfering with the development server.
  • Consider using the --force flag with npx next dev to force a full rebuild, although this is not a standard flag and may not be applicable.
  • Check if there are any open issues or discussions related to Turbopack and next/dynamic that might provide more insight into this caching behavior.
  • As a temporary workaround, avoid using next/dynamic with ssr: false for components that require frequent updates during development.

Example

No specific code example can be provided without inventing APIs or functions, but ensuring that all cache and temporary files are properly cleared before restarting the development server is crucial.

Notes

The provided environment information and steps to reproduce suggest that this issue is specific to the interaction between Turbopack, next/dynamic, and the development server's caching mechanisms. The fact that the issue does not occur without next/dynamic or when using static imports implies a problem with how Turbopack handles the module graph for lazy-loaded chunks.

Recommendation

Apply a workaround by avoiding the use of next/dynamic with ssr: false for components that are frequently updated during development, as this seems to be the most direct way to circumvent the caching issue until a more permanent solution is found.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING