Skip to content

Turbopack standalone build in 16.1.x omits serverExternalPackages from .next/standalone/node_modules #88844

@MTroian94

Description

@MTroian94

Link to the code that reproduces this issue

https://github.com/MTroian94/next-16.1.4

To Reproduce

  1. Create a new Next.js app using Next.js 16.1.x with Turbopack enabled.
  2. Install a dependency that will be externalized, for example: pnpm add ts-deepmerge
  3. Configure next.config.ts with output: "standalone" and serverExternalPackages:
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "standalone",
  serverExternalPackages: ["ts-deepmerge"],
};

export default nextConfig;
  1. Import and use ts-deepmerge in any server-side file (e.g. page.tsx)
  2. Run the build using Turobopack
next build
  1. Inspect the generated standalone output:
ls .next/standalone/node_modules

Observed result

  • ts-deepmerge is 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 without node_modules installation) 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 --webpack

which 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: standalone

Which 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/static

With 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    RuntimeRelated to Node.js or Edge Runtime with Next.js.TurbopackRelated to Turbopack with Next.js.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions