Bun 模块系统
Bun 支持多种模块系统,包括 ES Modules (ESM)、CommonJS (CJS) 和 Bun 专有的模块解析。本章介绍 Bun 的模块系统及其特性。
ES Modules (ESM)
ES Modules 是 JavaScript 的标准模块系统,也是 Bun 推荐使用的方式。
导出模块
typescript
// math.ts
// 命名导出
export const PI = 3.14159;
export function add(a: number, b: number): number {
return a + b;
}
export function multiply(a: number, b: number): number {
return a * b;
}
// 默认导出
export default class Calculator {
add(a: number, b: number) {
return a + b;
}
subtract(a: number, b: number) {
return a - b;
}
}导入模块
typescript
// main.ts
// 导入默认导出
import Calculator from "./math";
// 导入命名导出
import { PI, add, multiply } from "./math";
// 导入全部并命名
import * as math from "./math";
// 混合导入
import Calculator, { PI, add } from "./math";
// 使用
const calc = new Calculator();
console.log(calc.add(2, 3));
console.log(add(2, 3));
console.log(math.PI);动态导入
typescript
// 动态导入(返回 Promise)
async function loadModule() {
const math = await import("./math");
console.log(math.add(2, 3));
// 条件导入
if (process.env.NODE_ENV === "development") {
const devTools = await import("./dev-tools");
devTools.init();
}
}重新导出
typescript
// index.ts - 模块聚合
// 重新导出全部
export * from "./math";
export * from "./string";
// 重新导出部分
export { add, multiply } from "./math";
// 重命名导出
export { add as sum } from "./math";
// 重新导出默认导出
export { default as Calculator } from "./math";CommonJS (CJS)
Bun 完全支持 CommonJS 模块系统,确保与现有 Node.js 生态兼容。
CommonJS 导出
javascript
// utils.js
// 导出单个值
module.exports = function greet(name) {
return `Hello, ${name}!`;
};
// 导出多个值
module.exports = {
greet: function(name) {
return `Hello, ${name}!`;
},
farewell: function(name) {
return `Goodbye, ${name}!`;
}
};
// 使用 exports 快捷方式
exports.greet = function(name) {
return `Hello, ${name}!`;
};
exports.farewell = function(name) {
return `Goodbye, ${name}!`;
};CommonJS 导入
javascript
// main.js
// 导入整个模块
const utils = require("./utils");
console.log(utils.greet("Bun"));
// 解构导入
const { greet, farewell } = require("./utils");
console.log(greet("Bun"));ESM 与 CJS 互操作
在 ESM 中导入 CJS
typescript
// cjs-module.js (CommonJS)
module.exports = {
name: "CJS Module",
greet() {
return "Hello from CJS!";
}
};
// esm-main.ts (ESM)
import cjsModule from "./cjs-module.js";
console.log(cjsModule.greet());
// 命名导入也可以工作(Bun 会自动处理)
import { name, greet } from "./cjs-module.js";在 CJS 中导入 ESM
javascript
// esm-module.ts (ESM)
export const message = "Hello from ESM!";
export default { name: "ESM Module" };
// cjs-main.js (CommonJS)
// 使用动态 import()
const loadESM = async () => {
const esmModule = await import("./esm-module.ts");
console.log(esmModule.message);
console.log(esmModule.default);
};
loadESM();模块解析
解析顺序
Bun 按以下顺序解析模块:
- 内置模块:
bun:*、node:* - 绝对路径:
/path/to/module - 相对路径:
./module、../module - node_modules:向上查找 node_modules
文件扩展名
typescript
// Bun 会按顺序尝试以下扩展名
import { foo } from "./module";
// 尝试顺序:
// 1. ./module.ts
// 2. ./module.tsx
// 3. ./module.js
// 4. ./module.jsx
// 5. ./module/index.ts
// 6. ./module/index.tsx
// 7. ./module/index.js
// 8. ./module/index.jsx路径别名
在 tsconfig.json 中配置:
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}使用别名:
typescript
import { Button } from "@components/Button";
import { formatDate } from "@utils/date";
import config from "@/config";Bun 内置模块
bun 模块
typescript
// 直接使用 Bun 全局对象
console.log(Bun.version);
// 或导入 bun 模块
import { $ } from "bun";
await $`echo "Hello from Bun Shell"`;常用 bun:* 模块
typescript
// SQLite
import { Database } from "bun:sqlite";
// FFI(外部函数接口)
import { dlopen, FFIType } from "bun:ffi";
// 测试
import { test, expect } from "bun:test";
// 密码哈希
import { password } from "bun";Node.js 内置模块
Bun 支持大部分 Node.js 内置模块:
typescript
// 文件系统
import fs from "fs";
import { readFile } from "fs/promises";
// 路径处理
import path from "path";
// HTTP
import http from "http";
import https from "https";
// 其他常用模块
import os from "os";
import crypto from "crypto";
import util from "util";
import events from "events";
import stream from "stream";
import buffer from "buffer";使用 node: 前缀
typescript
// 推荐使用 node: 前缀(更明确)
import fs from "node:fs";
import path from "node:path";
import { Buffer } from "node:buffer";JSON 和其他文件导入
导入 JSON
typescript
// 直接导入 JSON
import config from "./config.json";
console.log(config.apiUrl);
// 类型安全的 JSON 导入
import packageJson from "./package.json" with { type: "json" };
console.log(packageJson.version);导入文本文件
typescript
// 导入为字符串
import readme from "./README.md" with { type: "text" };
console.log(readme);导入 TOML
typescript
// 导入 TOML 配置
import config from "./config.toml";
console.log(config.database.host);模块缓存
缓存机制
Bun 会缓存已加载的模块,同一模块只会执行一次:
typescript
// counter.ts
let count = 0;
export function increment() {
return ++count;
}
// main.ts
import { increment } from "./counter";
import { increment as inc } from "./counter";
console.log(increment()); // 1
console.log(inc()); // 2 (同一个模块实例)清除缓存
typescript
// 在测试中可能需要清除缓存
delete require.cache[require.resolve("./module")];循环依赖
处理循环依赖
typescript
// a.ts
import { b } from "./b";
export const a = "A";
console.log("a.ts loaded, b =", b);
// b.ts
import { a } from "./a";
export const b = "B";
console.log("b.ts loaded, a =", a);
// main.ts
import { a } from "./a";
// 输出:
// b.ts loaded, a = undefined
// a.ts loaded, b = B避免循环依赖
typescript
// 方法1: 延迟导入
export function getA() {
const { a } = require("./a");
return a;
}
// 方法2: 重构代码,提取共享模块
// shared.ts - 共享的代码
// a.ts - 导入 shared
// b.ts - 导入 sharedpackage.json 配置
type 字段
json
{
"type": "module" // 使用 ESM
}json
{
"type": "commonjs" // 使用 CJS(默认)
}exports 字段
json
{
"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"
}
}
}条件导出
json
{
"exports": {
".": {
"bun": "./src/index.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
}
}
}Bun 会优先使用 bun 条件。
小结
本章介绍了:
- ✅ ES Modules 的导入导出语法
- ✅ CommonJS 模块系统
- ✅ ESM 与 CJS 互操作
- ✅ 模块解析规则和路径别名
- ✅ Bun 和 Node.js 内置模块
- ✅ JSON、TOML 等文件导入
- ✅ 模块缓存和循环依赖处理
下一步
继续阅读 TypeScript 支持 了解 Bun 对 TypeScript 的原生支持。