YAML
通過 Bun 的執行環境 API 和打包器整合使用內建的 YAML 檔案支援
在 Bun 中,YAML 與 JSON 和 TOML 同等重要。你可以:
- 使用
Bun.YAML.parse解析 YAML 字串 - 在執行環境將 YAML 檔案作為模組進行
import和require(包括熱過載和 watch 模式支援) - 使用 Bun 的打包器在前端應用中
import和requireYAML 檔案
相容性
Bun 的 YAML 解析器使用 Rust 編寫,通過了官方 YAML 測試套件,覆蓋了絕大多數實際使用場景。
執行環境 API
Bun.YAML.parse()
將 YAML 字串解析為 JavaScript 物件。
TypeScript
import { YAML } from "bun";
const text = `
name: John Doe
age: 30
email: john@example.com
hobbies:
- reading
- coding
- hiking
`;
const data = YAML.parse(text);
console.log(data);
// {
// name: "John Doe",
// age: 30,
// email: "john@example.com",
// hobbies: ["reading", "coding", "hiking"]
// }
多文件 YAML
解析由多個文件(用 --- 分隔)構成的 YAML 時,Bun.YAML.parse() 傳回一個陣列:
TypeScript
const multiDoc = `
---
name: Document 1
---
name: Document 2
---
name: Document 3
`;
const docs = Bun.YAML.parse(multiDoc);
console.log(docs);
// [
// { name: "Document 1" },
// { name: "Document 2" },
// { name: "Document 3" }
// ]
支援的 YAML 特性
Bun 的 YAML 解析器支援 YAML 1.2 規範,包括:
- 標量:字串、數字、布林值、null 值
- 集合:序列(陣列)和對映(物件)
- 錨點和別名:使用
&和*定義可重用節點。別名集合共享同一物件身份。別名可以引用包含自身的集合,因此Bun.YAML.parse可以傳回迴圈物件。作為模組匯入的 YAML 不能包含迴圈引用。 - 標籤:型別提示,例如
!!str、!!int、!!float、!!bool、!!null - 多行字串:字面量(
|)和摺疊(>)標量 - 註釋:使用
# - 指令:
%YAML和%TAG
TypeScript
const yaml = `
# 員工記錄
employee: &emp
name: Jane Smith
department: Engineering
skills:
- JavaScript
- TypeScript
- React
manager: *emp # 引用員工
config: !!str 123 # 顯式字串型別
description: |
這是一個多行
文字字串,保留
換行和空格。
summary: >
這是一個摺疊字串,
用空格連線行,
除非有空白行。
`;
const data = Bun.YAML.parse(yaml);
錯誤處理
如果 YAML 無效,Bun.YAML.parse() 會丟擲 SyntaxError:
TypeScript
try {
Bun.YAML.parse("invalid: yaml: content:");
} catch (error) {
console.error("解析 YAML 失敗:", error.message);
}
模組匯入
ES 模組
直接將 YAML 檔案作為 ES 模組匯入。Bun 會解析其內容,並將其同時作為預設匯出和命名匯出提供:
config.yaml
database:
host: localhost
port: 5432
name: myapp
redis:
host: localhost
port: 6379
features:
auth: true
rateLimit: true
analytics: false
預設匯入
import config from "./config.yaml";
console.log(config.database.host); // "localhost"
console.log(config.redis.port); // 6379
命名匯入
頂層 YAML 屬性可作為命名匯入使用:
import { database, redis, features } from "./config.yaml";
console.log(database.host); // "localhost"
console.log(redis.port); // 6379
console.log(features.auth); // true
或者兩者結合:
import config, { database, features } from "./config.yaml";
// 使用完整設定物件
console.log(config);
// 或使用特定部分
if (features.rateLimit) {
setupRateLimiting(database);
}
CommonJS
你也可以在 CommonJS 中使用 require 匯入 YAML 檔案:
const config = require("./config.yaml");
console.log(config.database.name); // "myapp"
// 解構同樣有效
const { database, redis } = require("./config.yaml");
console.log(database.port); // 5432
YAML 熱過載
當你使用 bun --hot 執行應用程式時,Bun 會檢測 YAML 檔案的更改,並在不關閉連線的情況下重新載入它們。
設定熱過載範例
config.yaml
server:
port: 3000
host: localhost
features:
debug: true
verbose: false
import { server, features } from "./config.yaml";
console.log(`啟動伺服器,地址為 ${server.host}:${server.port}`);
if (features.debug) {
console.log("除錯模式已啟用");
}
// 伺服器程式碼
Bun.serve({
port: server.port,
hostname: server.host,
fetch(req) {
if (features.verbose) {
console.log(`${req.method} ${req.url}`);
}
return new Response("Hello World");
},
});
使用熱過載執行:
terminal
bun --hot server.ts
現在,當你修改 config.yaml 時,正在執行的應用程式會獲取更改:你可以在開發過程中調整設定或切換功能標誌,而無需重啟應用程式。
設定管理
基於環境的設定
一個 YAML 檔案可以儲存多個環境的設定,並通過錨點共享預設值:
config.yaml
defaults: &defaults
timeout: 5000
retries: 3
cache:
enabled: true
ttl: 3600
development:
<<: *defaults
api:
url: http://localhost:4000
key: dev_key_12345
logging:
level: debug
pretty: true
staging:
<<: *defaults
api:
url: https://staging-api.example.com
key: ${STAGING_API_KEY}
logging:
level: info
pretty: false
production:
<<: *defaults
api:
url: https://api.example.com
key: ${PROD_API_KEY}
cache:
enabled: true
ttl: 86400
logging:
level: error
pretty: false
import configs from "./config.yaml";
const env = process.env.NODE_ENV || "development";
const config = configs[env];
// YAML 值中的環境變數插值函式
function interpolateEnvVars(obj: any): any {
if (typeof obj === "string") {
return obj.replace(/\${(\w+)}/g, (_, key) => process.env[key] || "");
}
if (typeof obj === "object") {
for (const key in obj) {
obj[key] = interpolateEnvVars(obj[key]);
}
}
return obj;
}
export default interpolateEnvVars(config);
功能標誌設定
features.yaml
features:
newDashboard:
enabled: true
rolloutPercentage: 50
allowedUsers:
- admin@example.com
- beta@example.com
experimentalAPI:
enabled: false
endpoints:
- /api/v2/experimental
- /api/v2/beta
darkMode:
enabled: true
default: auto # auto, light, dark
import { features } from "./features.yaml";
export function isFeatureEnabled(featureName: string, userEmail?: string): boolean {
const feature = features[featureName];
if (!feature?.enabled) {
return false;
}
// 檢查釋出比例
if (feature.rolloutPercentage < 100) {
const hash = hashCode(userEmail || "anonymous");
if (hash % 100 >= feature.rolloutPercentage) {
return false;
}
}
// 檢查允許使用者列表
if (feature.allowedUsers && userEmail) {
return feature.allowedUsers.includes(userEmail);
}
return true;
}
// 與熱過載配合,實現即時切換功能
if (isFeatureEnabled("newDashboard", user.email)) {
renderNewDashboard();
} else {
renderLegacyDashboard();
}
資料庫設定
database.yaml
connections:
primary:
type: postgres
host: ${DB_HOST:-localhost}
port: ${DB_PORT:-5432}
database: ${DB_NAME:-myapp}
username: ${DB_USER:-postgres}
password: ${DB_PASS}
pool:
min: 2
max: 10
idleTimeout: 30000
cache:
type: redis
host: ${REDIS_HOST:-localhost}
port: ${REDIS_PORT:-6379}
password: ${REDIS_PASS}
db: 0
analytics:
type: clickhouse
host: ${ANALYTICS_HOST:-localhost}
port: 8123
database: analytics
migrations:
autoRun: ${AUTO_MIGRATE:-false}
directory: ./migrations
seeds:
enabled: ${SEED_DB:-false}
directory: ./seeds
import { connections, migrations } from "./database.yaml";
import { createConnection } from "./database-driver";
// 解析帶預設值的環境變數
function parseConfig(config: any) {
return JSON.parse(
JSON.stringify(config).replace(
/\${([^:-]+)(?::([^}]+))?}/g,
(_, key, defaultValue) => process.env[key] || defaultValue || "",
),
);
}
const dbConfig = parseConfig(connections);
export const db = await createConnection(dbConfig.primary);
export const cache = await createConnection(dbConfig.cache);
export const analytics = await createConnection(dbConfig.analytics);
// 如果設定自動執行遷移
if (parseConfig(migrations).autoRun === "true") {
await runMigrations(db, migrations.directory);
}
打包器整合
當你打包匯入 YAML 檔案的應用程式時,Bun 會在建置時解析 YAML,並將其作為 JavaScript 模組包含在內:
terminal
bun build app.ts --outdir=dist
在建置時解析意味著:
- 生產環境中無需執行環境解析 YAML
- 更小的打包體積
- 對未使用的設定進行搖樹最佳化(命名匯入)
動態匯入
動態匯入 YAML 檔案,按需載入設定:
TypeScript
// 根據環境載入設定
const env = process.env.NODE_ENV || "development";
const { default: config } = await import(`./configs/${env}.yaml`);
// 載入使用者特定設定
async function loadUserSettings(userId: string) {
try {
const settings = await import(`./users/${userId}/settings.yaml`);
return settings.default;
} catch {
const { default: defaults } = await import("./users/default-settings.yaml");
return defaults;
}
}