# How to Compile or Bundle Deno Applications: Native Executables and JS Bundles Explained

> Compile Deno apps into native executables or single JS bundles using deno compile and deno bundle. Distribute your Deno applications easily with these powerful tools.

- Repository: [Deno/deno](https://github.com/denoland/deno)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Deno provides two first-class commands for distributing applications—`deno compile` creates standalone native executables containing the V8 engine and runtime, while `deno bundle` generates single JavaScript files via esbuild integration suitable for browsers or Node.js.**

Deno offers robust tooling for shipping TypeScript and JavaScript applications without requiring end-users to install the runtime. Whether you need a self-contained binary for CLI tools or a portable module for web deployment, mastering how to compile or bundle Deno applications streamlines your production workflow. Both commands leverage Deno's advanced module resolution, npm integration, and TypeScript transpilation pipeline.

## Using `deno compile` to Build Native Executables

The `deno compile` command transforms your application into a self-contained native executable. This binary includes the JavaScript/TypeScript source, the V8 engine, and the Deno runtime, allowing distribution to users who do not have Deno installed.

### The Compilation Pipeline

According to the Deno source code in [[`cli/tools/compile.rs`](https://github.com/denoland/deno/blob/main/cli/tools/compile.rs)](https://github.com/denoland/deno/blob/main/cli/tools/compile.rs), the compilation process follows five distinct phases:

1. **Flag Parsing**: The CLI creates `CliOptions` from arguments and a `CompileFlags` struct that handles `--output`, `--target`, and permission flags.

2. **Temporary Node Modules**: When the entrypoint uses npm specifiers, the compiler creates a temporary `node_modules` directory via `create_temp_node_modules_dir` (lines 40-53) to resolve packages during the build.

3. **Module Graph Construction**: `CliFactory::from_flags` generates a factory that builds a **module graph** using `module_graph_creator.create_graph_and_maybe_check` (lines 88-105). This resolves all imports, applies TypeScript type checking if enabled, and produces a code-only graph.

4. **Binary Generation**: The `BinaryWriter` from `deno_runtime` (located in [`runtime/standalone/binary.rs`](https://github.com/denoland/deno/blob/main/runtime/standalone/binary.rs)) embeds the module graph into a self-extracting ELF, PE, or Mach-O binary. The writer outputs to a temporary file, sets executable permissions (`PermissionsExt::from_mode(0o755)`), and renames it to the final output path (lines 33-44, 77-85).

5. **Cross-Platform Naming**: The `get_os_specific_filepath` function automatically appends `.exe` when targeting Windows (lines 29-45), ensuring correct extensions regardless of the host platform.

### Cross-Platform Compilation

Deno supports cross-compilation through the `--target` flag. You can build Windows executables from Linux or macOS, and vice versa, by specifying the target triple:

```bash
deno compile --target x86_64-pc-windows-msvc --output app.exe ./main.ts

```

The compiler downloads the appropriate Deno runtime binary for the target architecture and embeds your application code, producing a fully standalone executable.

## Using `deno bundle` to Create JavaScript Bundles

The `deno bundle` command produces a single JavaScript file (ESM or IIFE) that runs in browsers, Node.js, or other JavaScript runtimes. This command delegates to esbuild via the `deno_bundle_runtime` crate, with core logic residing in [[`cli/tools/bundle/mod.rs`](https://github.com/denoland/deno/blob/main/cli/tools/bundle/mod.rs)](https://github.com/denoland/deno/blob/main/cli/tools/bundle/mod.rs).

### The Esbuild Integration Pipeline

The bundling workflow relies on three primary components defined in the source:

**Entry Resolution**: The `bundle_init` function (lines 26-38) resolves entry URLs using Deno's native resolver, ensuring import maps, npm specifiers, and Node.js built-ins are handled identically to normal execution.

**Plugin Bridge**: [[`cli/tools/bundle/provider.rs`](https://github.com/denoland/deno/blob/main/cli/tools/bundle/provider.rs)](https://github.com/denoland/deno/blob/main/cli/tools/bundle/provider.rs) implements `CliBundleProvider`, which acts as a bridge between Deno's module system and esbuild through three critical callbacks:
- `on_resolve`: Handles import resolution, virtual modules for HTML entrypoints, and external module marking (lines 35-115)
- `on_load`: Loads file contents including TypeScript transpilation, returning appropriate esbuild loader types (JS, TS, CSS, JSON) (lines 24-71)
- `on_end`: Delivers the final `BuildResponse` via async channel (lines 84-88)

**Post-Processing**: After esbuild completes, `process_result` applies optional transformations including `require` shim replacement for Deno compatibility and minification before writing to the `--output` location.

### HTML Entrypoints and Watch Mode

Deno supports bundling HTML files directly. When provided with an HTML entrypoint, the bundler generates a virtual module via `html::load_html_entrypoint` (lines 47-61) that imports all scripts referenced in the HTML, enabling complete application bundling including assets.

For development workflows, `bundle_watch` (in [`mod.rs`](https://github.com/denoland/deno/blob/main/mod.rs)) sets up a file watcher that rebuilds the bundle automatically when source files change.

## Choosing Between Compilation and Bundling

Select the appropriate command based on your distribution requirements:

- **Use `deno compile`** when you need a single binary that runs without Deno installed. Ideal for CLI tools, system utilities, or server applications where you want minimal deployment friction.

- **Use `deno bundle`** when targeting browsers, Node.js, or other JavaScript runtimes. Essential for frontend applications, library distribution, or environments where a full Deno runtime is unavailable.

- **Both support npm**: `compile` embeds a temporary `node_modules` tree into the binary, while `bundle` resolves npm specifiers through the esbuild plugin system.

## Practical Examples

Compile a script to a native binary with networking permissions:

```bash
deno compile --allow-net --output server ./server.ts

```

Cross-compile for Windows from macOS or Linux:

```bash
deno compile --target x86_64-pc-windows-msvc --output app.exe ./main.ts

```

Create a minified ESM bundle for browsers:

```bash
deno bundle --minify --output dist/app.min.js ./src/main.ts

```

Bundle an HTML entrypoint with all referenced scripts:

```bash
deno bundle --output-dir dist/ index.html

```

Enable watch mode for automatic rebuilds during development:

```bash
deno bundle --watch --output dist/bundle.js ./src/main.ts

```

## Summary

- **`deno compile`** produces standalone native executables by embedding your code with the V8 engine and Deno runtime using the `BinaryWriter` in [`runtime/standalone/binary.rs`](https://github.com/denoland/deno/blob/main/runtime/standalone/binary.rs).
- **`deno bundle`** generates portable JavaScript bundles using esbuild integration via [`cli/tools/bundle/mod.rs`](https://github.com/denoland/deno/blob/main/cli/tools/bundle/mod.rs) and the `CliBundleProvider` bridge.
- Both commands fully support npm packages, import maps, and TypeScript transpilation through Deno's resolver system.
- Cross-compilation is available via `--target` flags, while bundling offers `--watch` mode and HTML entrypoint support for comprehensive asset management.

## Frequently Asked Questions

### What is the difference between `deno compile` and `deno bundle`?

`deno compile` creates a native binary executable specific to your operating system (or cross-compilation target) that contains the Deno runtime, allowing the program to run without Deno installed. `deno bundle` produces a single JavaScript file that requires a JavaScript runtime (like Deno, Node.js, or a browser) to execute, making it suitable for web deployment or environments where you cannot install native binaries.

### Can I cross-compile Deno applications for different platforms?

Yes. The `deno compile` command supports cross-compilation through the `--target` flag, accepting platform triples like `x86_64-pc-windows-msvc`, `x86_64-unknown-linux-gnu`, or `aarch64-apple-darwin`. According to the implementation in [`cli/tools/compile.rs`](https://github.com/denoland/deno/blob/main/cli/tools/compile.rs), the compiler automatically handles OS-specific filename extensions (such as `.exe` for Windows) via `get_os_specific_filepath` regardless of your host platform.

### Does `deno bundle` support npm packages?

Yes. The bundler resolves npm specifiers through the same resolver used by the runtime, implemented in [`cli/tools/bundle/provider.rs`](https://github.com/denoland/deno/blob/main/cli/tools/bundle/provider.rs). The `on_resolve` callback handles npm package resolution and external module marking, allowing you to bundle applications that depend on npm dependencies alongside Deno's native modules.

### How does Deno handle HTML entrypoints when bundling?

When bundling an HTML file, Deno generates a virtual entry module using `html::load_html_entrypoint` (found in [`cli/tools/bundle/mod.rs`](https://github.com/denoland/deno/blob/main/cli/tools/bundle/mod.rs)). This virtual module imports all scripts referenced in the HTML file, allowing esbuild to trace dependencies and bundle the entire application including JavaScript, CSS, and assets into the output directory.