โครงสร้างโปรเจกต์
จาก package.json ถึง Cargo.toml
หัวข้อที่มีชื่อว่า “จาก package.json ถึง Cargo.toml”ทุกโปรเจกต์ Node.js เริ่มด้วย package.json ส่วนของเทียบเท่าใน Rust คือ Cargo.toml ซึ่งประกาศชื่อ crate, version และ dependency ตัว Cargo เองเป็นทั้ง package manager และ build tool — ไม่ต้องแยก npm กับ tsc กับ ts-node
flowchart TD root["my-api/ (Express/NestJS project)"] --> pkg["package.json — dependencies + scripts"] root --> tsc["tsconfig.json — TypeScript compiler config"] root --> src["src/"] src --> main["main.ts — entry point"] src --> appmod["app.module.ts — (NestJS) root module"] src --> users["users/"] users --> ctrl["users.controller.ts"] users --> svc["users.service.ts"] users --> mod["users.module.ts"] root --> dist["dist/ — compiled output"]
flowchart TD root["my-api/ (Axum project)"] --> toml["Cargo.toml — dependencies + metadata (= package.json)"] root --> lock["Cargo.lock — lockfile (= package-lock.json)"] root --> src["src/"] src --> main["main.rs — entry point"] src --> routes["routes/"] routes --> rmod["mod.rs — route definitions"] src --> handlers["handlers/"] handlers --> husers["users.rs — handler functions"] src --> models["models.rs — serde structs (request/response types)"] src --> state["state.rs — shared AppState"] src --> errors["errors.rs — custom error types"]
Cargo.toml สำหรับ Axum service
หัวข้อที่มีชื่อว่า “Cargo.toml สำหรับ Axum service”[package]name = "my-api"version = "0.1.0"edition = "2021"
[dependencies]axum = "0.7"tokio = { version = "1", features = ["full"] }serde = { version = "1", features = ["derive"] }serde_json = "1"tower = "0.4"tower-http = { version = "0.5", features = ["cors", "trace"] }tracing = "0.1"tracing-subscriber = { version = "0.3", features = ["env-filter"] }sqlx = { version = "0.7", features = ["postgres", "runtime-tokio-rustls", "uuid"] }uuid = { version = "1", features = ["v4", "serde"] }thiserror = "1"เทียบกับ npm install express คุณประกาศทุกอย่างในไฟล์เดียวและ Cargo จะแก้ไข dependency graph, compile ทุกอย่าง และ link เข้าด้วยกัน — ไม่ต้องมีขั้นตอน build แยกต่างหาก
main.rs — entry point
หัวข้อที่มีชื่อว่า “main.rs — entry point”use axum::Router;use std::net::SocketAddr;
mod errors;mod handlers;mod models;mod routes;mod state;
#[tokio::main]async fn main() { // initialise structured logging tracing_subscriber::fmt() .with_env_filter("my_api=debug,tower_http=debug") .init();
let state = state::AppState::new().await; let app = routes::create_router(state);
let addr = SocketAddr::from(([0, 0, 0, 0], 3000)); tracing::info!("Listening on {addr}");
let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap();}#[tokio::main] คือ macro ที่ wrap main ใน Tokio async runtime — เทียบได้กับ event loop ของ Node ที่เริ่มต้นโดยอัตโนมัติ
แนวคิดสำคัญ
หัวข้อที่มีชื่อว่า “แนวคิดสำคัญ”| Node/TS | Rust/Axum |
|---|---|
package.json | Cargo.toml |
npm install | cargo add / cargo build |
ts-node src/main.ts | cargo run |
tsc --build | cargo build --release |
nodemon | cargo-watch -x run |
src/app.ts | src/main.rs |
process.env.PORT | std::env::var("PORT") |
รันบนเครื่องของคุณ — นี่คือบทเรื่องโครงสร้างโปรเจกต์ ไม่มี snippet ที่รันใน browser ได้ สร้างโปรเจกต์ด้วย
cargo new my-apiและเพิ่ม dependencies ด้วยcargo add axum tokio serde serde_json