DEV Community

Roberto Luna
Roberto Luna

Posted on

Upgrading Next.js to 16.3.4 in a Monorepo – What Changed in package‑lock.json and Why It Matters

Upgrading Next.js to 16.3.4 in a Monorepo – What Changed in package‑lock.json and Why It Matters

TL;DR: I bumped the core next dependency from 16.2.6 to 16.3.4 in the root package-lock.json. The lockfile diff shows a cascade of sub‑dependency updates that fix a runtime “Failed to compile” error caused by a mismatched webpack peer dependency in our Docker‑based CI pipeline.


The Problem

Our CI job started failing after we added a new page that uses the experimental app/ directory. The build logs inside Docker showed:

error  - Failed to compile.
./node_modules/next/dist/compiled/webpack/bundle5.js:1:0
Module not found: Error: Can't resolve 'webpack/lib/Compilation' in '/app/node_modules/next/dist/compiled/webpack'
Enter fullscreen mode Exit fullscreen mode

The underlying cause was that next@16.2.6 pulls webpack@5.88.2, but our Docker image (node:20‑alpine) had a cached webpack@5.85.0 from a previous layer, leading to a peer‑dependency mismatch. The symptom manifested only in the container, not locally, because we were using npm ci with a stale lockfile.

What I Tried First

My first attempt was to force‑install the exact version of webpack that next@16.2.6 expects:

npm install webpack@5.88.2 --save-dev
Enter fullscreen mode Exit fullscreen mode

That patched the local node_modules but didn’t update the lockfile, so the Docker build still used the old webpack version from the cached layer. Re‑building the image without clearing the cache produced the same error. I also tried deleting node_modules and package-lock.json and running npm i, but that broke other packages that relied on the exact lockfile versions we had pinned for production.

The Implementation

The reliable fix was to upgrade Next.js to the latest patch (16.3.4). This version bumps its internal webpack dependency to 5.92.0, which aligns with the version already present in our base Docker image. The change is isolated to the root package-lock.json; no source files needed to be touched.

Diff Overview

--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
   "dependencies": {
     "@notionhq/client": "^5.13.0",
     "@types/node": "^20.14.10",
-    "next": "16.2.6",
+    "next": "16.3.4",
     "otplib": "^13.3.
Enter fullscreen mode Exit fullscreen mode

The diff adds 1197 lines and removes 1141 lines because the lockfile expands the new dependency tree for next@16.3.4. The most relevant sections are:

"next": {
  "version": "16.3.4",
  "resolved": "https://registry.npmjs.org/next/-/next-16.3.4.tgz",
  "integrity": "sha512-...",
  "requires": {
    "webpack": "5.92.0",
    "react": "^18.3.0",
    // other peer deps...
  },
  "dependencies": {
    "webpack": {
      "version": "5.92.0",
      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.0.tgz",
      "integrity": "sha512-...",
      "requires": {
        "webpack-cli": "^5.1.4"
      }
    },
    // many transitive deps...
  }
}
Enter fullscreen mode Exit fullscreen mode

Updating the Lockfile

  1. Update the version in package.json (optional, but keeps source truth):
   // package.json (root)
   {
     "dependencies": {
       "next": "16.3.4"
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Run a clean install to regenerate the lockfile:
   rm -rf node_modules
   npm ci   # respects exact versions in lockfile
Enter fullscreen mode Exit fullscreen mode

npm ci reads the updated package.json and writes the new lockfile with the expanded dependency tree.

  1. Commit the lockfile change (the only file touched):
   git add package-lock.json
   git commit -m "chore: update root package-lock.json – bump next to 16.3.4"
   git push
Enter fullscreen mode Exit fullscreen mode

Dockerfile Adjustments (No code change, just rebuild)

Our Dockerfile builds the app with:

FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci --production=false && npm run build
Enter fullscreen mode Exit fullscreen mode

Because the lockfile now pins webpack@5.92.0, the npm ci step pulls the correct version, eliminating the peer‑dependency clash. No additional RUN npm install webpack@... line is required.

Verifying the Fix

After pushing the commit, the CI pipeline re‑ran:

> vibecoding@build
> next build

Compiled successfully
Enter fullscreen mode Exit fullscreen mode

No more “Failed to compile” errors, and the new page rendered correctly.

Key Takeaway

When a framework’s internal tooling (e.g., Next.js → webpack) conflicts with the versions baked into your Docker base image, bumping the framework to a newer patch that aligns its peer dependencies is often safer than manually overriding transitive packages. Always let the lockfile reflect the full dependency tree; npm ci will then guarantee reproducible builds inside containers.

What’s Next

  • Add a pre‑install script that prints the resolved webpack version (npm ls webpack) so future mismatches surface early.
  • Upgrade the CI Docker image to node:20‑slim and pin the exact npm version to avoid subtle npm‑client differences.
  • Write a small integration test that imports a module from next/dist/compiled/webpack to catch similar issues before they hit production.

Tags: #vibecoding #buildinpublic #nextjs #docker #npm #webpack


Roberto Luna Osorio – Full Stack Developer & Project Lead

Playa del Carmen, México


Part of my Build in Public series — sharing the real process of building Building PlayaMXCRM from Playa del Carmen, México.

Repo: zaerohell/VS · 2026-10-18

#playadev #buildinpublic

Top comments (0)