Skip to content

esbuild is imported at build time but not declared as a dependency — works only by hoisting accident, breaks under npm ci #1339

Description

@fabio-miguel

Version: @opennextjs/cloudflare 1.20.2 (also inspected 1.20.x line)

@opennextjs/cloudflare imports esbuild during opennextjs-cloudflare build, but declares it only in its own devDependencies (^0.27.0) — consumers don't get it. In practice the import resolves against @opennextjs/aws's nested esbuild (pinned 0.25.4) only when npm happens to hoist it to the consumer's top level.

How it breaks: any consumer whose dependency graph claims that hoist slot loses the build. In our case, adding @vitejs/plugin-react hoisted vite, whose optional esbuild peer (^0.27.0 || ^0.28.0) reserved the top-level slot without filling it (optional peers are omitted by npm 11), demoting aws's copy → npx opennextjs-cloudflare build fails with ERR_MODULE_NOT_FOUND: Cannot find package 'esbuild'.

The nasty variant: a fresh npm install can build a tree that works while writing the lockfile entry for esbuild as "extraneous": truenpm ci then refuses to install it, so local builds pass and CI/build machines fail from the same committed lockfile.

Workaround: declare esbuild in the consumer's own devDependencies, pinned inside your declared range (we used ^0.27.0).

Suggested fix: add esbuild to @opennextjs/cloudflare's dependencies (or re-export/bundle it), so the build-time import is satisfied by contract rather than by hoisting luck.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions