Skip to content

fix: inline named webpack chunks (webpackChunkName) in the server runtime - #1439

Merged
vicb merged 5 commits into
opennextjs:mainfrom
mathurshubham:mathurshubham/oss-11-1326-webpack-runtime-chunk-inlining-misses-named-chunks
Oct 16, 2026
Merged

vicb merged 5 commits into
opennextjs:mainfrom
mathurshubham:mathurshubham/oss-11-1326-webpack-runtime-chunk-inlining-misses-named-chunks

Conversation

@mathurshubham

@mathurshubham mathurshubham commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1326

Problem

The webpack server runtime loads chunks with installChunk(require("./chunks/" + __webpack_require__.u(chunkId))), which esbuild cannot bundle, so the adapter rewrites it into a switch with one static require per chunk. That rewrite only listed chunks/<digits>.js and switched on the numeric id. Next's server chunkFilename is [name].js, so a chunk named with /* webpackChunkName: "x" */ (from next/dynamic or a dependency) is written as chunks/x.js and reached through the __webpack_require__.u id-to-name map (e.u=a=>""+(522===a?"x":a)+".js"). It had no case, so the page failed with Error: Unknown chunk 522 and a 500.

Fix

patchWebpackRuntime now lists every .js under chunks/ (nested names like dir/name included, symlinks accepted) and the generated code switches on the computed path:

if (SELF_ID == chunkId) {
  installedChunks[chunkId] = 1;
} else {
  switch ("./chunks/" + __webpack_require__.u(chunkId)) {
    case "./chunks/103.js": installChunk(require("./chunks/103.js")); break;
    case "./chunks/named-chunk.js": installChunk(require("./chunks/named-chunk.js")); break;
    default: throw new Error(`Unknown chunk ${chunkId}`);
  }
}

The single-chunk rule uses the same switch so a single named chunk also loads. Chunk names are escaped ($ to \x24) so they can't collide with the $NAME placeholders of the ast-grep fix template. The chunk listing is skipped when no webpack runtime file exists (Turbopack builds).

Testing

  • Spec: updated snapshots, plus new cases for pretty and minified __webpack_require__.u maps, nested names, a single named chunk, a $ in the name, an executable test that runs the patched runtime, and applyRule(...).edits.length no-op checks.
  • Old vs new rule were run over the production webpack runtimes of Next 15.2, 15.5 and 16.3 (pages and api runtimes): identical match counts, no require("./chunks/"+ left behind.
  • New e2e in examples/e2e/pages-router: /named-chunk/ renders a next/dynamic component with webpackChunkName. Built handler.mjs contains case"./chunks/named-chunk.js" for both runtimes; the full pages-router Playwright suite passes (40 passed, 1 skipped).
  • pnpm test and pnpm code:checks pass.

Note: examples/e2e/pages-router is periodically synced from opennextjs-aws; the new test may need to be upstreamed there as well.


Devin Review

…untime

The webpack runtime patch only inlined `chunks/<digits>.js` and switched on
the numeric chunk id, so a chunk named with `/* webpackChunkName */` (written
as `chunks/<name>.js` and reached through the `__webpack_require__.u`
id-to-filename map) hit `default: throw new Error("Unknown chunk N")` at
runtime.

List every `.js` file under `chunks/` (nested names included) and switch on
the computed path `"./chunks/" + __webpack_require__.u(chunkId)` instead of
the id. Chunk names are escaped so they cannot collide with the `$NAME`
placeholders of the fix template. The single chunk rule uses the same
switch so a single named chunk also loads.

Adds a pages-router e2e page using `next/dynamic` with a named chunk.

Fixes opennextjs#1326
@changeset-bot

changeset-bot Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a8b267d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@opennextjs/cloudflare Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Devin Review: 1 flag

Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

A non-matching rule used to leave the dynamic require in place silently
and the worker would only fail when loading a chunk at runtime.
@mathurshubham

Copy link
Copy Markdown
Contributor Author

Devin Review reports one flag on this PR but it is not posted here (hidden by the org's review settings), so I could not read it. I re-reviewed the diff against the webpack template shipped in Next 15.5.27 and 16.3.8 and the emitted webpack-runtime.js / webpack-api-runtime.js, and added one hardening change in 3859688: when neither rule matches, the patch now logs an error instead of silently leaving the dynamic require("./chunks/" + ...) in place (which would only surface as a runtime failure). Verified on a fresh pages-router worker build: chunks/named-chunk.js is emitted and referenced from the bundle, no dynamic chunk require remains, and the new guard does not fire. If the hidden flag is about something else, please share it and I will address it.

vicb added 3 commits October 16, 2026 10:37
Apps in examples/e2e come from `@opennextjs/aws` so it's better not to add tests only for cloudflare if they can be added to a cloudflare specific app
@pkg-pr-new

pkg-pr-new Bot commented Oct 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@opennextjs/cloudflare@1439

commit: a8b267d

@vicb vicb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @mathurshubham!

The e2e was super helpful to investigate.

I moved the e2e to the playground16 app because apps under examples/e22 are shared with the aws adapter.

The last commit simplifies the implementation.

@vicb
vicb merged commit 1ebbc55 into opennextjs:main Oct 16, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] webpack-runtime chunk inlining misses named chunks (chunkFilename id→name map) — "Unknown chunk N" at runtime

2 participants