How to Configure Module Resolution and Import Aliases in Bun Projects
Bun reads the paths field from your tsconfig.json to resolve import aliases at runtime, eliminating the need for extra build tools or plugins.
The Bun JavaScript runtime (oven-sh/bun) provides native support for custom module resolution through TypeScript configuration files. By leveraging the compilerOptions.paths mapping, you can replace verbose relative imports like ../../../utils with clean aliases such as @utils/*. This configuration works immediately during development, testing, and production bundling without requiring Babel transforms or third-party resolvers.
How Bun Resolves Module Aliases Internally
When Bun encounters an import or require statement, it invokes the private API resolve(specifier, referrer) declared in src/js/private.d.ts (line 151). This function serves as the unified entry point for both CommonJS and ESM module resolution.
For CommonJS modules, the built-in overridableRequire function (implemented in src/js/builtins/CommonJS.ts) calls the internal $resolveSync helper, passing any options.paths derived from your tsconfig.json configuration (line 18). The same resolution logic applies to ES modules because Bun's ESM loader ultimately delegates to this identical resolve routine.
Bun extracts the "paths" map from src/tsconfig.json (line 6) and applies these mappings before executing the standard Node.js module resolution algorithm. This precedence ensures that aliases override node_modules packages when conflicts occur.
Configuring Path Aliases in tsconfig.json
Bun uses tsconfig.json as the single source of truth for import aliasing, supporting wildcards and base URL resolution.
Setting Up the Configuration File
Create or modify tsconfig.json at your project root. Bun automatically discovers this file by walking up the directory tree from the importing module until it finds a configuration.
Defining Path Mappings
Add a compilerOptions.paths object to map alias patterns to concrete file locations. The baseUrl field determines the starting directory for relative paths in your mappings.
{
"compilerOptions": {
"target": "es2022",
"module": "esnext",
"moduleResolution": "bundler",
"baseUrl": ".",
"paths": {
"@app/*": ["src/app/*"],
"@lib/*": ["src/lib/*"],
"config": ["src/config/index.ts"]
}
}
}
In this configuration:
@app/*resolves to files within thesrc/app/directory@lib/*maps tosrc/lib/- The bare specifier
configpoints directly tosrc/config/index.ts
Overriding Configuration Location
If your tsconfig.json resides in a non-standard location, use the --tsconfig-override CLI flag. According to the API schema in src/api/schema.d.ts (line 549), Bun accepts a string path to an alternative configuration:
bun run --tsconfig-override ./configs/tsconfig.dev.json index.ts
Practical Implementation Example
Consider a project with the following structure:
/src
/app
main.ts
/lib
helpers.ts
/config
index.ts
tsconfig.json
With the tsconfig.json configuration shown above, you can write src/app/main.ts as:
import { helper } from "@lib/helpers";
import config from "config";
console.log(helper(), config);
Executing bun run src/app/main.ts resolves @lib/helpers to src/lib/helpers.ts and config to src/config/index.ts automatically. No relative path traversal (../../lib/helpers) is required.
Resolution Behavior and Fallbacks
Bun's resolution algorithm follows a specific precedence order to maintain compatibility while enabling customization:
- Path alias matching – Patterns from
tsconfig.jsonare evaluated first - Node_modules resolution – Standard Node.js algorithm executes if no alias matches
- File extension handling – Bun automatically resolves
.ts,.tsx,.js, and.jsxextensions
If a specifier does not match any configured pattern, Bun falls back to the standard Node.js module resolution algorithm. This guarantees that existing packages continue to function normally alongside your custom aliases.
Advanced Usage Patterns
Monorepo Configuration
For monorepos containing multiple packages, place individual tsconfig.json files in each package directory. Bun stops at the first configuration file encountered while traversing upward from the importing module, allowing package-specific alias definitions.
Integration with Testing and Bundling
Since Bun's test runner (bun test) utilizes the same resolver as the runtime, your path aliases work immediately in test files without additional configuration. Similarly, the bundler (bun build) reads the paths map during the build process, ensuring that emitted bundles contain correctly resolved paths rather than the alias specifiers.
Summary
- Bun natively supports import aliases through the
pathsfield intsconfig.json, requiring zero additional tooling - Resolution occurs via the internal
resolve()function insrc/js/private.d.ts, used by both CommonJS and ESM loaders - The
overridableRequireimplementation insrc/js/builtins/CommonJS.tsdemonstrates how runtime path overrides are applied - Wildcard patterns and
baseUrlconfiguration provide flexible mapping options for complex project structures - Aliases function identically across development, testing (
bun test), and production bundling (bun build)
Frequently Asked Questions
Does Bun support jsconfig.json for path aliases?
Currently, Bun primarily reads path mappings from tsconfig.json. While jsconfig.json follows a similar schema, Bun's resolver specifically targets the TypeScript configuration file as implemented in the resolution logic. You should use tsconfig.json even for pure JavaScript projects to enable alias resolution.
Can I use import aliases without installing TypeScript?
Yes. Although Bun reads the tsconfig.json file format, you do not need to install the TypeScript compiler or run tsc. Bun parses this configuration natively during its own module resolution phase, making the aliases available immediately at runtime without compilation steps.
How do path aliases affect the bun build output?
When running bun build, the bundler resolves path aliases during the compilation process and replaces them with the actual relative paths to the target files. The final bundle contains the resolved module contents rather than the alias specifiers, ensuring compatibility with environments that lack Bun's resolver.
What happens if a path alias matches a node_modules package?
Bun evaluates tsconfig.json path aliases before checking node_modules. If you define an alias like "lodash": ["./src/my-lodash"], Bun will import your local implementation instead of the npm package. This behavior enables powerful mocking and local override capabilities for testing or customization purposes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →