Workspace & Feature Flag
npm workspaces → cargo workspaces
หัวข้อที่มีชื่อว่า “npm workspaces → cargo workspaces”เมื่อ TypeScript monorepo เติบโตเกิน package เดียว คุณจะใช้ npm (หรือ pnpm/yarn) workspaces Cargo มีเทียบเท่าแบบ first-class: workspace คือ Cargo.toml เดียวที่ root ซึ่งระบุ member crate ทั้งหมด member ทั้งหมดใช้ Cargo.lock เดียวและ target/ build directory เดียวร่วมกัน
# package.json (root){ "name": "my-monorepo", "workspaces": [ "packages/api", "packages/core", "packages/cli" ]}
# packages/core/package.json{ "name": "@my/core", "version": "1.0.0"}# Cargo.toml (root — workspace manifest)[workspace]members = [ "crates/api", "crates/core", "crates/cli",]resolver = "2" # ใช้ resolver version 2 เสมอ
# crates/core/Cargo.toml[package]name = "core"version = "0.1.0"edition = "2021"รัน command ทั้ง workspace
หัวข้อที่มีชื่อว่า “รัน command ทั้ง workspace”# TypeScript (npm workspaces)npm run test --workspacesnpm run build --workspace packages/api
# Cargocargo build --workspace # build ทุก membercargo test --workspace # test ทุก membercargo build -p api # build เฉพาะ crate "api"cargo test -p core # test เฉพาะ crate "core"Share dependency version ข้าม crate
หัวข้อที่มีชื่อว่า “Share dependency version ข้าม crate”# Cargo.toml (root workspace manifest)[workspace.dependencies]tokio = { version = "1", features = ["full"] }serde = { version = "1", features = ["derive"] }
# crates/api/Cargo.toml — inherit โดยไม่ต้องระบุ version ซ้ำ[dependencies]tokio = { workspace = true }serde = { workspace = true }วิธีนี้กัน version drift ข้าม workspace member ที่เป็นปัญหาที่พบบ่อยใน Node monorepo ที่ package ต่างตัวดึง patch version ไม่ตรงกันโดยไม่รู้ตัว
Feature flag — conditional compilation
หัวข้อที่มีชื่อว่า “Feature flag — conditional compilation”Feature flag คือคำตอบของ Rust สำหรับ optional peer dependency และการเรียก require() แบบมีเงื่อนไข ช่วยให้ผู้ใช้เลือกใช้ฟังก์ชันเพิ่มเติมโดยไม่ต้องจ่าย compile cost เมื่อไม่ต้องการ
[features]default = ["json"] # feature ที่เปิดโดย defaultjson = ["dep:serde_json"] # feature "json" ดึง serde_json เข้ามาasync = ["dep:tokio"] # feature "async" ดึง tokio เข้ามาfull = ["json", "async"] # ความสะดวก: เปิดทุกอย่าง
[dependencies]serde_json = { version = "1", optional = true }tokio = { version = "1", optional = true }#[cfg(feature = "json")]pub mod json_support { pub fn parse(s: &str) -> serde_json::Value { serde_json::from_str(s).unwrap() }}# Build โดยไม่มี default featurecargo build --no-default-features
# เปิด feature เฉพาะcargo build --features "async,json"
# เปิดทุก featurecargo build --all-featuresWorkspace และ feature flag ต้องการ project layout หลาย file จึงไม่มี browser Playground สำหรับบทนี้ สร้าง workspace ใน local ด้วย
cargo new --libและทดลองกับตัวอย่างข้างต้น