Skip to content

Bundle Deployment

Egg can bundle an application into a self-contained, deployable CommonJS artifact using @eggjs/egg-bundler, driven by the egg-bin bundle command. The bundle inlines your application code, framework, plugins, and dependencies into a small set of chunks that boot in Egg's single-process mode — useful for fast cold starts, smaller deploy images, and serverless targets.

Bundling builds on the Startup Manifest: the bundler reuses the manifest's file-discovery, module-resolution, and tegg module metadata so the bundled app skips filesystem scanning at runtime.

Build

bash
$ egg-bin bundle

This writes the artifact to ./dist-bundle by default. Common options:

OptionDescription
--output <dir>Output directory. Defaults to ./dist-bundle.
--mode <mode>production (default) or development.
--framework <pkg>Framework package specifier. Defaults to egg (or pkg.egg.framework).
--force-externalPackage name to always keep external (repeatable).
--inline-externalPackage name to force-inline even if auto-detected as external.

Most apps need no --force-external flags: the bundler auto-detects packages that must stay external (native addons, optional platform packages, packages with native bindings, and unresolved optional peers) and inlines everything else, including egg and @eggjs/*.

If <baseDir>/.egg/manifest.json is missing, the bundler generates it first by starting the app with metadataOnly: true (which runs loadMetadata() hooks and exits without booting the agent or normal lifecycle).

Configuration via module.yml

Apps can declare stable bundle configuration in <baseDir>/module.yml:

yaml
bundle:
  runtimeAssets:
    # Directories scanned for runtime assets (default: app).
    roots:
      - app
    # Directories copied verbatim even for source-like files (default:
    # app/public, app/assets, app/static).
    forceCopyDirs:
      - app/public
      - app/assets
  pack:
    resolve:
      alias:
        some-package: ./node_modules/some-package/index.js

Output

dist-bundle/
├── worker.js                 # synthetic worker entry produced by the bundler
├── _root-of-the-server__*.js # @utoo/pack module-graph chunks (opaque names)
├── _turbopack__runtime.js    # @utoo/pack runtime shim
├── app/...                   # copied runtime assets (html/static, etc.)
├── tsconfig.json             # written for the SWC compiler
├── package.json              # { "type": "commonjs" }
└── bundle-manifest.json      # reference metadata (externals, chunks, ...)

See the output structure reference for full details.

Run

Packages classified as external are not inlined and must be installed alongside the bundle. The simplest way is to copy the app's package.json next to worker.js and install production dependencies:

bash
$ cd dist-bundle
$ cp ../package.json .
$ npm ci --omit=dev
$ node worker.js

The worker entry installs the bundle's manifest store and module loader, then starts Egg with baseDir set to the output directory in mode: 'single', so the agent runs in-process with the worker.

Limitations

  • Single process only: the bundle runs in mode: 'single', so the agent runs in-process with the worker. Cluster-mode bundles are not yet supported.
  • Native addons are always external and must be present in the deploy target.
  • External packages must be installed next to worker.js (see Run).

Born to build better enterprise frameworks and apps