Skip to content

v17 ESM exports break Next.js standalone builds - \index.mjs missing from standalone output #4828

Description

@thaoms

After upgrading from graphql@16 to graphql@17, Next.js standalone builds fail at runtime with:

Error: Failed to load external module graphql-0ad5f9b0af23869e: Error: Cannot find module
'/code/apps/platform/.next/node_modules/graphql-0ad5f9b0af23869e/index.mjs'

Works fine in local dev. Only fails when running from the standalone output (i.e. Docker).

Environment

  • graphql: 17.0.1
  • @apollo/client: 4.2.3
  • next: 16.2.9 (Turbopack)
  • pnpm workspace, output: "standalone"

Root cause

graphql v17 added "module": "./index.mjs" and "default": "./index.mjs" to its exports map. Turbopack resolves graphql (imported by Apollo Client internals) via the module/default condition, picks index.mjs, and externalizes the package to .next/node_modules//index.mjs.

The Next.js file tracer (@vercel/nft) that creates the standalone build copies .js files from that directory into the standalone output — but skips .mjs files. So index.mjs is absent in production and the SSR runtime crashes on every request.

What doesn't work

  • transpilePackages: ["graphql"] — Turbopack panics: "transpilePackages" conflicts with "serverExternalPackages": ["graphql"]. Graphql is auto-added to Turbopack's internal external list and can't be removed via config.
  • serverExternalPackages: ["graphql"] — no effect, it's already there internally, still resolves to index.mjs.
  • outputFileTracingIncludes: { "/": ["./.next/node_modules//*.mjs"] } — ignored, the file tracer skips .next/node_modules/ regardless.

Workaround

Pin to graphql@^16. v16 has no index.mjs entry so Turbopack externalizes to index.js, which the file tracer does include in standalone.


Note on where this belongs: Not sure if this should be filed here or at vercel/next.js. The triggering change is the v17 export map, but the actual failure is in the file tracer — it creates .next/node_modules//index.mjs during the build and then doesn't include it in the standalone output. Filing here first since that's where the export map lives, but happy to move it if you think it belongs at Next.js.

Also worth noting: the v17 docs say the development export condition is supported by "Webpack 5, Rspack, Rollup, esbuild, Vite, Rsbuild, and Next.js when using Webpack 5" — Turbopack is not listed. Was standalone mode tested against Turbopack?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions