> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# Module Resolution

> How Bun resolves and loads JavaScript modules

Bun implements a sophisticated module resolution system compatible with Node.js, enhanced with additional features for modern JavaScript development.

## Module Systems

Bun supports both ES Modules (ESM) and CommonJS (CJS):

### ES Modules

```javascript ES Modules theme={null}
// Importing
import { readFile } from "node:fs/promises";
import React from "react";
import { add } from "./math.js";

// Exporting
export function greet(name) {
  return `Hello, ${name}!`;
}

export default App;
```

**Features:**

* Static imports and exports
* Top-level `await` support
* Tree-shaking friendly
* Strict mode by default

### CommonJS

```javascript CommonJS theme={null}
// Importing
const fs = require("node:fs");
const React = require("react");
const { add } = require("./math.js");

// Exporting
module.exports = {
  greet(name) {
    return `Hello, ${name}!`;
  },
};

module.exports.default = App;
```

**Features:**

* Dynamic `require()` calls
* Synchronous loading
* Circular dependency handling
* `exports` shorthand

### Interoperability

Bun seamlessly bridges ESM and CommonJS:

```javascript ESM → CommonJS theme={null}
// Import CommonJS from ESM
import pkg from "./commonjs-module.js"; // module.exports
import { named } from "./commonjs-module.js"; // module.exports.named
```

```javascript CommonJS → ESM theme={null}
// Require ESM from CommonJS (async)
const esm = await import("./esm-module.js");
```

Implementation: `src/runtime.zig:167` - CommonJS named exports feature

## Resolution Algorithm

Bun's module resolution follows the Node.js algorithm with enhancements:

### Resolution Steps

1. **Built-in modules** - Check for `node:*` and `bun:*` modules
2. **Relative/absolute paths** - Resolve file paths
3. **Package imports** - Search `node_modules`
4. **Extensions** - Try `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs`
5. **Index files** - Check `index.*` files
6. **package.json** - Resolve via `exports`, `main`, `module`

### Relative Imports

```javascript Relative imports theme={null}
import { util } from "./utils.js"; // Same directory
import { config } from "../config.js"; // Parent directory
import { helper } from "./lib/helper.js"; // Subdirectory
```

### Absolute Imports

```javascript Absolute imports theme={null}
import { db } from "/src/database.js"; // From root
import data from "file:///home/user/data.json"; // file:// URL
```

### Package Imports

```javascript Package imports theme={null}
import React from "react"; // node_modules/react
import { parse } from "@babel/parser"; // Scoped package
import "./styles.css"; // Side-effect import
```

## Extension Resolution

Bun tries extensions in this order:

1. Exact match (if extension provided)
2. `.ts`
3. `.tsx`
4. `.js`
5. `.jsx`
6. `.mjs`
7. `.cjs`
8. `.json`

```javascript Extension resolution theme={null}
// All resolve to math.ts if it exists:
import { add } from "./math.ts"; // Explicit
import { add } from "./math"; // Implicit
```

**Explicit extensions recommended** for clarity and performance.

## package.json Fields

Bun respects multiple package.json fields:

### exports Field

Modern package entry points:

```json package.json theme={null}
{
  "name": "my-package",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    },
    "./utils": {
      "import": "./dist/utils.mjs",
      "require": "./dist/utils.cjs"
    }
  }
}
```

**Import usage:**

```javascript theme={null}
import pkg from "my-package"; // Uses exports["."]
import { util } from "my-package/utils"; // Uses exports["./utils"]
```

### Conditional Exports

```json Conditional exports theme={null}
{
  "exports": {
    ".": {
      "bun": "./dist/bun.js",
      "node": "./dist/node.js",
      "browser": "./dist/browser.js",
      "default": "./dist/index.js"
    }
  }
}
```

**Condition priority** (Bun target):

1. `bun`
2. `node`
3. `import` / `require`
4. `default`

Implementation: `src/options.zig:508-533` - Default conditions per target

### main, module, browser

Legacy entry point fields:

```json Legacy fields theme={null}
{
  "main": "./dist/index.js",      // CommonJS entry
  "module": "./dist/index.mjs",   // ESM entry
  "browser": "./dist/browser.js", // Browser entry
  "types": "./dist/index.d.ts"    // TypeScript types
}
```

**Resolution priority**:

1. `exports` (if present)
2. `module`
3. `main`
4. `index.js`

Implementation: `src/options.zig:455-505` - Main field resolution

### type Field

Determines module system:

```json package.json theme={null}
{
  "type": "module" // All .js files are ESM
}
```

```json package.json theme={null}
{
  "type": "commonjs" // All .js files are CommonJS (default)
}
```

Overrides:

* `.mjs` always ESM
* `.cjs` always CommonJS

## Path Mapping (tsconfig.json)

Configure import aliases:

```json tsconfig.json theme={null}
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@lib/*": ["./src/lib/*"],
      "~/*": ["./*"]
    }
  }
}
```

```javascript Using path aliases theme={null}
import { Button } from "@components/Button";
import { api } from "@lib/api";
import config from "@/config";
import data from "~/data/users.json";
```

Implementation: `src/resolver/resolver.zig` - Path resolution

## Built-in Modules

Bun provides built-in modules:

### Node.js Compatibility

```javascript Node.js modules theme={null}
import fs from "node:fs";
import path from "node:path";
import { EventEmitter } from "node:events";
import { createServer } from "node:http";
```

**All Node.js built-ins available** with `node:` prefix.

Implementation: `src/options.zig:150-333` - Node.js built-in patterns

### Bun-specific Modules

```javascript Bun modules theme={null}
import { serve } from "bun";
import { Database } from "bun:sqlite";
import { dlopen, FFIType } from "bun:ffi";
import { password } from "bun:password";
import { spawn } from "bun:spawn";
```

**Available modules:**

* `bun` - Main Bun APIs
* `bun:ffi` - Foreign Function Interface
* `bun:sqlite` - SQLite database
* `bun:test` - Test runner
* `bun:jsc` - JavaScriptCore internals
* `bun:wrap` - Internal runtime

## Import Attributes

Specify how to import modules:

```javascript Import attributes theme={null}
// Import as JSON
import data from "./data.json" with { type: "json" };

// Import as text
import content from "./file.txt" with { type: "text" };

// Import assertions (older syntax)
import config from "./config.json" assert { type: "json" };
```

**Supported types:**

* `json` - Parse as JSON
* `text` - Load as string
* `file` - Copy to output
* `toml` - Parse as TOML

## Dynamic Imports

Load modules at runtime:

```javascript Dynamic imports theme={null}
// ESM dynamic import
const module = await import("./module.js");

// Conditional loading
if (isDevelopment) {
  const dev = await import("./dev-tools.js");
  dev.init();
}

// Dynamic path
const locale = "en";
const messages = await import(`./locales/${locale}.js`);
```

**Benefits:**

* Code splitting
* Lazy loading
* Conditional imports
* String-based paths

## Circular Dependencies

Bun handles circular dependencies:

```javascript Circular dependencies theme={null}
// a.js
import { b } from "./b.js";
export const a = "A";
console.log(b); // "B"

// b.js
import { a } from "./a.js";
export const b = "B";
console.log(a); // undefined (not yet initialized)
```

**Best practice:** Avoid circular dependencies when possible.

## Import Maps

Map bare specifiers to URLs:

```json import-map.json theme={null}
{
  "imports": {
    "react": "https://esm.sh/react@18",
    "lodash": "https://esm.sh/lodash@4"
  }
}
```

```javascript Using import maps theme={null}
import React from "react"; // Loads from esm.sh
import _ from "lodash";
```

<Note>
  Import maps are experimental and primarily for browser compatibility.
</Note>

## Resolution Cache

Bun caches module resolution results:

**Cache location:**

* Resolution cache: In-memory
* Transpiler cache: Disk (see [TypeScript](/runtime/typescript))

**Cache invalidation:**

* File system changes (watch mode)
* package.json modifications
* node\_modules updates

## Module Loader Hooks

Customize module loading (advanced):

```javascript Module hooks theme={null}
import { plugin } from "bun";

plugin({
  name: "custom-loader",
  setup(build) {
    // Custom resolution
    build.onResolve({ filter: /^@app/ }, (args) => {
      return {
        path: args.path.replace("@app", "./src"),
      };
    });

    // Custom loading
    build.onLoad({ filter: /\.custom$/ }, async (args) => {
      const text = await Bun.file(args.path).text();
      return {
        contents: `export default ${JSON.stringify(text)}`,
        loader: "js",
      };
    });
  },
});
```

## Preloading

Load modules before main script:

```bash Preload flag theme={null}
bun --preload ./setup.ts run app.ts
```

```toml bunfig.toml theme={null}
preload = ["./setup.ts", "./polyfills.ts"]
```

**Use cases:**

* Environment setup
* Polyfills
* Global initialization
* Instrumentation

## Performance

### Optimization Tips

1. **Use explicit extensions**
   ```javascript theme={null}
   import { util } from "./util.ts"; // Fast
   import { util } from "./util"; // Slower (tries multiple extensions)
   ```

2. **Prefer ESM over CommonJS**
   * Static analysis
   * Tree-shaking
   * Async loading

3. **Use barrel files sparingly**
   ```javascript theme={null}
   // Slow (loads entire barrel)
   import { Button } from "./components/index.js";

   // Fast (direct import)
   import { Button } from "./components/Button.js";
   ```

4. **Leverage dynamic imports for code splitting**
   ```javascript theme={null}
   const Chart = await import("./Chart.js");
   ```

## Debugging

### Trace Resolution

```bash Debug resolution theme={null}
BUN_DEBUG_QUIET_LOGS=0 bun run app.ts 2>&1 | grep -i resolve
```

### Print Resolved Paths

```javascript Print resolution theme={null}
console.log(import.meta.resolveSync("react"));
// "/path/to/node_modules/react/index.js"
```

### Resolution Failures

```bash Common errors theme={null}
# Module not found
error: Cannot find module "./missing.js"

# Check if file exists
ls -la ./missing.js

# Check extensions
ls -la ./missing.*
```

## Implementation Details

Module resolution implementation:

* **Resolver**: `src/resolver/resolver.zig` - Core resolution logic
* **Module loader**: `src/bun.js/module_loader/` - Module loading
* **Import record**: `src/import_record.zig` - Import tracking
* **Package.json**: `src/resolver/package_json.zig` - Package metadata

## Related

* [Loaders](/runtime/loaders) - File type handling
* [TypeScript](/runtime/typescript) - Path mapping configuration
* [bunfig.toml](/runtime/bunfig) - Module configuration
* [Package Manager](/package-manager) - Installing dependencies
