Bun宏 BunMacros

Bun 宏是一种在构建时执行 JavaScript 代码并将结果内联到捆绑输出中的技术,适用于编译时代码生成、环境变量嵌入、文件嵌入等场景,提高开发效率和构建性能。关键词:Bun 宏, 构建时代码执行, JavaScript 捆绑, 编译时优化, 环境变量内联, 文件嵌入, 代码生成。

DevOps 0 次安装 0 次浏览 更新于 3/8/2026

name: Bun 宏 description: 在捆绑时评估 JavaScript 并将结果内联。用于优化编译时代码生成、嵌入文件、内联环境变量或在捆绑过程中执行代码。 version: 1.0.0

Bun 宏

Bun 宏在捆绑时运行 JavaScript 并将结果内联到输出中。

快速开始

// src/config.ts (宏文件)
export function getVersion() {
  return "1.0.0";
}

export function getBuildTime() {
  return new Date().toISOString();
}

// src/index.ts (消费者)
import { getVersion, getBuildTime } from "./config" with { type: "macro" };

// 在捆绑时,这些变为:
const version = "1.0.0";
const buildTime = "2024-01-15T12:00:00.000Z";

宏语法

// 使用宏属性导入
import { fn } from "./macro-file" with { type: "macro" };

// 调用宏(在构建时评估)
const result = fn();

常见使用案例

环境变量内联

// macros/env.ts
export function env(key: string): string {
  return process.env[key] ?? "";
}

// src/index.ts
import { env } from "./macros/env" with { type: "macro" };

const apiUrl = env("API_URL");
// 变为:const apiUrl = "https://api.example.com";

Git 信息

// macros/git.ts
export function gitCommit(): string {
  return Bun.spawnSync(["git", "rev-parse", "HEAD"])
    .stdout.toString().trim();
}

export function gitBranch(): string {
  return Bun.spawnSync(["git", "branch", "--show-current"])
    .stdout.toString().trim();
}

// src/index.ts
import { gitCommit, gitBranch } from "./macros/git" with { type: "macro" };

const BUILD_INFO = {
  commit: gitCommit(),
  branch: gitBranch(),
};
// 在构建时内联

文件嵌入

// macros/embed.ts
export function embedFile(path: string): string {
  return Bun.file(path).text();
}

export function embedJSON(path: string): unknown {
  return Bun.file(path).json();
}

// src/index.ts
import { embedFile, embedJSON } from "./macros/embed" with { type: "macro" };

const license = embedFile("./LICENSE");
const config = embedJSON("./config.json");

构建常量

// macros/constants.ts
export function isDev(): boolean {
  return process.env.NODE_ENV !== "production";
}

export function buildDate(): number {
  return Date.now();
}

export function randomId(): string {
  return Math.random().toString(36).slice(2);
}

// src/index.ts
import { isDev, buildDate, randomId } from "./macros/constants" with { type: "macro" };

if (isDev()) {
  console.log("开发模式");
}

const BUILD_ID = randomId();

目录列表

// macros/files.ts
import { readdirSync } from "fs";

export function listRoutes(): string[] {
  return readdirSync("./src/routes")
    .filter(f => f.endsWith(".tsx"))
    .map(f => f.replace(".tsx", ""));
}

// src/router.ts
import { listRoutes } from "./macros/files" with { type: "macro" };

const routes = listRoutes();
// 变为:const routes = ["home", "about", "users"];

代码生成

// macros/codegen.ts
export function generateTypes(schema: string): string {
  // 在构建时解析模式并生成类型
  const types = parseSchemaToTypes(schema);
  return types;
}

export function generateAPI(spec: string): string {
  const openapi = JSON.parse(Bun.file(spec).text());
  // 生成 API 客户端代码
  return generateClientFromOpenAPI(openapi);
}

返回类型

宏可以返回:

// 原始类型
export function getString(): string { return "hello"; }
export function getNumber(): number { return 42; }
export function getBoolean(): boolean { return true; }
export function getNull(): null { return null; }

// 对象(可序列化)
export function getObject(): object {
  return { key: "value", nested: { a: 1 } };
}

// 数组
export function getArray(): string[] {
  return ["a", "b", "c"];
}

// 响应(用于捆绑器插件)
export function getResponse(): Response {
  return new Response("内容", {
    headers: { "Content-Type": "text/plain" },
  });
}

异步宏

// macros/fetch.ts
export async function fetchSchema(): Promise<object> {
  const response = await fetch("https://api.example.com/schema.json");
  return response.json();
}

// src/index.ts
import { fetchSchema } from "./macros/fetch" with { type: "macro" };

const schema = await fetchSchema();
// 在构建时获取,内联为对象字面量

参数

// macros/parameterized.ts
export function repeat(str: string, count: number): string {
  return str.repeat(count);
}

export function formatDate(format: string): string {
  return new Date().toLocaleDateString("en-US", {
    dateStyle: format as any,
  });
}

// src/index.ts
import { repeat, formatDate } from "./macros/parameterized" with { type: "macro" };

const separator = repeat("-", 20);
const date = formatDate("long");

条件代码

// macros/platform.ts
export function platform(): "node" | "bun" | "browser" {
  if (typeof Bun !== "undefined") return "bun";
  if (typeof process !== "undefined") return "node";
  return "browser";
}

// src/index.ts
import { platform } from "./macros/platform" with { type: "macro" };

if (platform() === "bun") {
  // 这个块在构建时保留或移除
  console.log("在 Bun 上运行");
}

仅捆绑时执行

宏仅在捆绑过程中运行:

# 宏执行
bun build src/index.ts --outdir=dist

# 宏不执行(运行时)
bun run src/index.ts

错误处理

// macros/safe.ts
export function requireEnv(key: string): string {
  const value = process.env[key];
  if (!value) {
    throw new Error(`缺少必需的环境变量: ${key}`);
  }
  return value;
}

// 如果环境变量缺失,构建失败
import { requireEnv } from "./macros/safe" with { type: "macro" };
const secret = requireEnv("API_SECRET");

调试宏

// macros/debug.ts
export function debug(label: string, value: unknown): unknown {
  console.log(`[MACRO] ${label}:`, value);
  return value;
}

// 在构建期间查看输出
bun build src/index.ts --outdir=dist
// [MACRO] config: { ... }

最佳实践

  1. 保持宏纯净 - 避免副作用
  2. 返回可序列化值 - 必须是 JSON 兼容的
  3. 处理错误 - 抛出有意义的错误以供构建失败
  4. 记录依赖 - 注明所需文件/环境变量
  5. 单独测试 - 宏可以作为常规函数测试

常见错误

错误 原因 修复
找不到模块 错误的导入路径 检查宏文件位置
不可序列化 返回函数/类 返回纯数据
宏失败 宏中的运行时错误 单独调试宏
未评估 缺少 with { type: "macro" } 添加导入属性

何时加载参考

加载 references/advanced-patterns.md 当:

  • 复杂代码生成
  • 插件集成
  • 构建管道 检索并展示自定义宏实现模式、与构建系统集成示例以及高级捆绑器插件工作流。

加载 references/debugging.md 当:

  • 宏未评估
  • 意外输出
  • 性能问题 检索调试技术,提供逐步诊断,并提供针对用户具体问题的优化策略。