-
Notifications
You must be signed in to change notification settings - Fork 30.3k
Description
Link to the code that reproduces this issue
https://github.com/MTroian94/next-16.1.4
To Reproduce
- Create a new Next.js app using Next.js 16.1.x with Turbopack enabled.
- Install a dependency that will be externalized, for example:
pnpm add ts-deepmerge - Configure
next.config.tswithoutput: "standalone"andserverExternalPackages:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
serverExternalPackages: ["ts-deepmerge"],
};
export default nextConfig;- Import and use ts-deepmerge in any server-side file (e.g.
page.tsx) - Run the build using Turobopack
next build- Inspect the generated standalone output:
ls .next/standalone/node_modulesObserved result
ts-deepmergeis not present in.next/standalone/node_modules.
Current vs. Expected behavior
Current behavior (Next.js 16.1.x + Turbopack)
When building a project with:
- output: "standalone"
- serverExternalPackages configured
- default Turbopack build (next build)
dependencies listed in serverExternalPackages (e.g. ts-deepmerge) are not included in .next/standalone/node_modules.
As a consequence:
- the standalone output is incomplete
- runtime execution fails with a missing module error, for example:
Error: Cannot find module 'ts-deepmerge'
- Docker images that rely exclusively on
.next/standalone(e.g. distroless images withoutnode_modulesinstallation) cannot start.
Expected behavior
Dependencies specified in serverExternalPackages should be:
- resolved at runtime via
.next/standalone/node_modules - included in the standalone output, as they were in Next.js ≤ 16.0.x
- consistently included regardless of whether the build uses Webpack or Turbopack
This is the current behavior when running:
next build --webpackwhich produces a correct standalone output including ts-deepmerge.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:34 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T8112
Available memory (MB): 8192
Available CPU cores: 8
Binaries:
Node: 22.22.0
npm: 10.9.4
Yarn: 1.22.22
pnpm: 10.28.0
Relevant Packages:
next: 16.1.4 // Latest available version is detected (16.1.4).
eslint-config-next: N/A
react: 19.2.3
react-dom: 19.2.3
typescript: 5.9.3
Next.js Config:
output: standaloneWhich area(s) are affected? (Select all that apply)
Runtime, Turbopack
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
Behavior up to Next.js 16.0.x
Up to Next.js 16.0.x, after running next build, the generated .next/standalone folder had the following structure:
.next/
└─ standalone/
├─ .next
├─ server.js
├─ package.json
├─ node_modules/
│ └─.pnpm
│ └─next
│ └─react
│ └─react-dom
│ └─ts-deepmerge
│ └─typescript
As expected, ts-deepmerge was correctly included in .next/standalone/node_modules.
Behavior up to Next.js 16.0.x
After upgrading to Next.js 16.1.x, ts-deepmerge is no longer present in .next/standalone/node_modules when building with Turbopack.
Workaround
If I run the build using Webpack instead:
next build --webpack
The generated .next folder has ts-deepmerge inside .next/standalone/node_modules folder.
Impact on Docker standalone builds
This behavior causes a concrete issue when using a Docker setup based on output: "standalone".
My Dockerfile follows the recommended multi-stage approach, where the runtime image only copies the contents of .next/standalone and .next/static, without installing node_modules again:
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/staticWith Next.js 16.1.x + Turbopack, since ts-deepmerge is no longer included in .next/standalone/node_modules, the runtime container fails at startup with a missing dependency error.
Because the final image is based on a distroless Node.js image and does not run pnpm install (by design), there is no way for the missing dependency to be resolved at runtime.
Using next build --webpack restores the previous behavior and produces a correct standalone output, which suggests a regression or behavior change specific to Turbopack in 16.1.x.
I have found a similar issue about this #87686