SIGN IN SIGN UP
denoland / deno UNCLAIMED

A modern runtime for JavaScript and TypeScript.

0 0 16 Rust

feat(unstable): add --bundle flag to `deno compile` (#34527)

First cut at making `deno compile` ship a bundled entrypoint instead of
embedding the entire `node_modules/` tree verbatim. Motivated by a
real-world report comparing `deno compile` against `bun build --compile`
on a 2700-module CLI, where Deno's binary was ~3x bigger almost entirely
because of the raw npm payload. The flag is gated behind a "this is
experimental" warning since several real cases aren't handled yet.

When `--bundle` is set, the entrypoint is run through the existing
esbuild-based bundler (ESM, platform=Deno, packages=Bundle,
tree-shaking on) and the bundle is written to a temp `.mjs` next to the
source. The standalone binary writer then sees a single self-contained
file in the graph, so the existing managed-npm path naturally skips the
VFS fill (no `Module::Npm` entries left after tree-shaking). The BYONM
path, which fills the VFS unconditionally, is gated on the new flag.
The existing `replace_require_shim` rewrite is reused so esbuild's
"Dynamic require not supported" stub becomes a real
`createRequire(import.meta.url)` call against `node:module`, so dynamic
`require()` of `node:` builtins keeps working in denort.

Known limitations for this PR (intentional, to keep it reviewable):
native `.node` addons, worker entrypoints, and any module that does
dynamic `require(path.join(__dirname, ...))` aren't traced and will
break. CJS npm packages are also currently externalized by esbuild as a
runtime `require()` against `node_modules`, which `--bundle` strips, so
those break too; this is locked in by an expected-failure spec
(`compile/bundle/npm_cjs_unsupported`) that should be removed once CJS
packages are inlined into the bundle. The warning calls out the
experimental status.
B
Bartek Iwańczuk committed
4ec12da8796b2d54d8428f9e2042c3e9f0532667
Parent: 3393603
Committed by GitHub <noreply@github.com> on 5/31/2026, 8:07:38 AM