名称: bun-打包工具 用户可调用: 否 描述: 使用 Bun 的快速打包工具打包 JavaScript/TypeScript 代码。涵盖为不同目标构建、树摇、代码分割和优化策略。 允许工具:
- 读取
- 写入
- 编辑
- Bash
- Grep
- Glob
Bun 打包工具
当使用 Bun 内置的打包工具打包 JavaScript/TypeScript 应用程序时,使用此技能,它提供卓越的性能和现代功能。
关键概念
基本打包
Bun 可以为不同目标打包您的代码:
# 为 Bun 运行时打包
bun build ./src/index.ts --outdir ./dist
# 为浏览器打包
bun build ./src/index.ts --outdir ./dist --target=browser
# 为 Node.js 打包
bun build ./src/index.ts --outdir ./dist --target=node
# 最小化输出
bun build ./src/index.ts --outdir ./dist --minify
编程 API
在 TypeScript 中使用 Bun 的构建 API:
import { build } from "bun";
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
target: "bun",
minify: true,
sourcemap: "external",
});
构建目标
Bun 支持多个构建目标:
bun- 为 Bun 运行时优化(默认)browser- 浏览器兼容的打包node- Node.js 兼容的打包
输出格式
控制输出格式:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
format: "esm", // 或 "cjs", "iife"
});
最佳实践
入口点配置
为复杂应用程序定义多个入口点:
await build({
entrypoints: [
"./src/client/index.ts",
"./src/server/index.ts",
"./src/worker.ts",
],
outdir: "./dist",
naming: {
entry: "[dir]/[name].[ext]",
chunk: "[name]-[hash].[ext]",
asset: "assets/[name]-[hash].[ext]",
},
});
树摇
Bun 自动树摇未使用的代码:
// utils.ts
export function used() {
return "used";
}
export function unused() {
return "unused";
}
// index.ts
import { used } from "./utils";
console.log(used()); // 仅 'used' 函数会被打包
代码分割
分割代码以提高加载性能:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
splitting: true, // 启用代码分割
target: "browser",
});
环境变量
在构建时替换环境变量:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
define: {
"process.env.API_URL": JSON.stringify("https://api.example.com"),
"process.env.NODE_ENV": JSON.stringify("production"),
},
});
外部依赖
标记依赖为外部以从打包中排除:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
external: ["react", "react-dom"], // 不打包 React
target: "browser",
});
源映射
为调试生成源映射:
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
sourcemap: "external", // 或 "inline", "none"
minify: true,
});
常见模式
构建库
// build.ts
import { build } from "bun";
// ESM 构建
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist/esm",
format: "esm",
target: "node",
minify: true,
sourcemap: "external",
});
// CJS 构建
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist/cjs",
format: "cjs",
target: "node",
minify: true,
sourcemap: "external",
});
console.log("构建完成!");
构建 Web 应用程序
// build.ts
import { build } from "bun";
await build({
entrypoints: ["./src/index.tsx"],
outdir: "./dist",
target: "browser",
format: "esm",
minify: true,
splitting: true,
sourcemap: "external",
publicPath: "/assets/",
naming: {
entry: "[dir]/[name].[ext]",
chunk: "[name]-[hash].[ext]",
asset: "assets/[name]-[hash].[ext]",
},
define: {
"process.env.NODE_ENV": JSON.stringify("production"),
},
});
构建多个输出
// build.ts
import { build } from "bun";
const builds = [
{
entrypoints: ["./src/index.ts"],
outdir: "./dist/esm",
format: "esm" as const,
target: "browser" as const,
},
{
entrypoints: ["./src/index.ts"],
outdir: "./dist/cjs",
format: "cjs" as const,
target: "node" as const,
},
{
entrypoints: ["./src/index.ts"],
outdir: "./dist/iife",
format: "iife" as const,
target: "browser" as const,
},
];
for (const config of builds) {
await build({
...config,
minify: true,
sourcemap: "external",
});
}
console.log("所有构建完成!");
带监听的构建脚本
// watch-build.ts
import { watch } from "fs";
import { build } from "bun";
async function buildApp() {
console.log("正在构建...");
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
target: "bun",
});
console.log("构建完成!");
}
// 初始构建
await buildApp();
// 监听变化
watch("./src", { recursive: true }, async (event, filename) => {
console.log(`文件已更改: ${filename}`);
await buildApp();
});
插件系统
创建自定义构建插件:
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(build) {
build.onLoad({ filter: /\.custom$/ }, async (args) => {
const text = await Bun.file(args.path).text();
return {
contents: `export default ${JSON.stringify(text)}`,
loader: "js",
};
});
},
};
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
plugins: [myPlugin],
});
反模式
不要为 Node 目标打包 Node 模块
// 错误 - 为 Node 打包所有依赖
await build({
entrypoints: ["./src/server.ts"],
target: "node",
// 缺少外部配置
});
// 正确 - 标记依赖为外部
await build({
entrypoints: ["./src/server.ts"],
target: "node",
external: ["express", "mongoose", "*"], // "*" 排除所有 node_modules
});
不要忽略构建错误
// 错误 - 无错误处理
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
});
// 正确 - 处理构建错误
try {
const result = await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
});
if (!result.success) {
console.error("构建失败");
process.exit(1);
}
console.log("构建成功");
} catch (error) {
console.error("构建错误:", error);
process.exit(1);
}
不要最小化开发构建
// 错误 - 总是最小化
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
minify: true, // 在开发中难以调试
});
// 正确 - 条件最小化
const isDev = Bun.env.NODE_ENV === "development";
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
minify: !isDev,
sourcemap: isDev ? "inline" : "external",
});
不要过度分割代码
// 错误 - 过度代码分割
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
splitting: true,
target: "bun", // Bun 目标不需要代码分割
});
// 正确 - 仅在有益时分割
await build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
splitting: true,
target: "browser", // 对浏览器有益
});
相关技能
- bun-runtime: 理解 Bun 运行时以进行目标优化
- bun-package-manager: 管理构建依赖
- bun-testing: 测试打包后的代码