package.json
Copy {
"name": "simple-blog",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "nodemon src/server.ts",
"build": "tsc",
"start": "node dist/server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"description": "",
"dependencies": {
"@types/cors": "^2.8.17",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"mongoose": "^8.11.0"
},
"devDependencies": {
"@types/express": "^5.0.0",
"@types/node": "^22.13.8",
"nodemon": "^3.1.9",
"ts-node": "^10.9.2",
"typescript": "^5.8.2"
}
}
.env
Copy MONGO_URI=mongodb://127.0.0.1:27017/simpleblog
PORT=5000
src\server.ts
Copy import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import connectDB from "./config/db";
import postRoutes from "./routes/postRoutes";
dotenv.config();
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
// Kết nối MongoDB
connectDB();
// Routes
app.use("/api/posts", postRoutes);
// Lắng nghe cổng
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server đang chạy trên cổng ${PORT}`));
src\routes\postRoutes.ts
Copy import express from "express";
import { createPost, deletePost, getPostById, getPosts, updatePost } from "../controllers/postController";
const router = express.Router();
router.get("/", getPosts);
router.post("/", createPost);
router.get("/:id", getPostById);
router.put("/:id", updatePost);
router.delete("/:id", deletePost);
export default router;
src\models\Post.ts
Copy import mongoose from "mongoose";
const postSchema = new mongoose.Schema(
{
title: { type: String, required: true },
content: { type: String, required: true },
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
export default Post;
src\controllers\postController.ts
Copy import { Request, Response } from "express";
import Post from "../models/Post";
// Lấy danh sách bài viết
export const getPosts = async (req: Request, res: Response) => {
try {
const posts = await Post.find();
res.json(posts);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Tạo bài viết mới
export const createPost = async (req: Request, res: Response) => {
try {
const { title, content } = req.body;
const newPost = new Post({ title, content });
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Lấy bài viết theo ID
export const getPostById = async (req: Request, res: Response) => {
try {
const { id } = req.params;
const post = await Post.findById(id);
res.status(200).json(post);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Cập nhật bài viết
export const updatePost = async (req: Request, res: Response) => {
const { id } = req.params;
try {
const updatedPost = await Post.findByIdAndUpdate(id, req.body, { new: true });
res.json(updatedPost);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Xóa bài viết
export const deletePost = async (req: Request, res: Response) => {
try {
const deletedPost = await Post.findByIdAndDelete(req.params.id);
res.json({ message: "Xóa thành công" });
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
src\config\db.ts
Copy import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI as string);
console.log("MongoDB Connected!");
} catch (error) {
console.error("MongoDB Connection Error:", error);
process.exit(1);
}
};
export default connectDB;
Dưới đây là một blog đơn giản sử dụng Node.js, TypeScript và MongoDB. Nó bao gồm các API cơ bản để tạo, đọc, cập nhật và xóa bài viết.
Công nghệ sử dụng
Node.js + Express.js : Framework backend
TypeScript : Giúp code dễ đọc và bảo trì hơn
MongoDB : Cơ sở dữ liệu NoSQL để lưu bài viết
Mongoose : ORM để làm việc với MongoDB
1. Khởi tạo dự án
Chạy các lệnh sau để tạo project:
Copy mkdir simple-blog
cd simple-blog
npm init -y
Cài đặt các package cần thiết:
Copy npm install express mongoose dotenv cors
npm install --save-dev typescript @types/express @types/node ts-node nodemon
Khởi tạo TypeScript:
2. Cấu trúc thư mục
Copy simple-blog/
│── src/
│ ├── models/
│ │ ├── Post.ts
│ ├── routes/
│ │ ├── postRoutes.ts
│ ├── controllers/
│ │ ├── postController.ts
│ ├── config/
│ │ ├── db.ts
│ ├── server.ts
│── .env
│── package.json
│── tsconfig.json
3. Kết nối MongoDB
Tạo file .env
:
Copy MONGO_URI=mongodb://127.0.0.1:27017/simpleblog
PORT=5000
Tạo file src/config/db.ts
:
Copy import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI as string);
console.log("MongoDB Connected!");
} catch (error) {
console.error("MongoDB Connection Error:", error);
process.exit(1);
}
};
export default connectDB;
4. Định nghĩa Model
Tạo file src/models/Post.ts
Copy import mongoose from "mongoose";
const postSchema = new mongoose.Schema(
{
title: { type: String, required: true },
content: { type: String, required: true },
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
export default Post;
5. Tạo Controller
Tạo file src/controllers/postController.ts
:
Copy import { Request, Response } from "express";
import Post from "../models/Post";
// Lấy danh sách bài viết
export const getPosts = async (req: Request, res: Response) => {
try {
const posts = await Post.find();
res.json(posts);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Tạo bài viết mới
export const createPost = async (req: Request, res: Response) => {
try {
const { title, content } = req.body;
const newPost = new Post({ title, content });
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Lấy bài viết theo ID
export const getPostById = async (req: Request, res: Response) => {
try {
const post = await Post.findById(req.params.id);
// if (!post) return res.status(404).json({ message: "Không tìm thấy bài viết" });
res.json(post);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Cập nhật bài viết
export const updatePost = async (req: Request, res: Response) => {
try {
const updatedPost = await Post.findByIdAndUpdate(req.params.id, req.body, { new: true });
// if (!updatedPost) return res.status(404).json({ message: "Không tìm thấy bài viết" });
res.json(updatedPost);
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
// Xóa bài viết
export const deletePost = async (req: Request, res: Response) => {
try {
const deletedPost = await Post.findByIdAndDelete(req.params.id);
// if (!deletedPost) return res.status(404).json({ message: "Không tìm thấy bài viết" });
res.json({ message: "Xóa thành công" });
} catch (error) {
res.status(500).json({ message: "Lỗi server" });
}
};
6. Định nghĩa Routes
Tạo file src/routes/postRoutes.ts
:
Copy import express from "express";
import { getPosts, createPost, getPostById, updatePost, deletePost } from "../controllers/postController";
const router = express.Router();
router.get("/", getPosts);
router.post("/", createPost);
router.get("/:id", getPostById);
router.put("/:id", updatePost);
router.delete("/:id", deletePost);
export default router;
7. Cấu hình Server
Tạo file src/server.ts
:
Copy import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import connectDB from "./config/db";
import postRoutes from "./routes/postRoutes";
dotenv.config();
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
// Kết nối MongoDB
connectDB();
// Routes
app.use("/api/posts", postRoutes);
// Lắng nghe cổng
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server đang chạy trên cổng ${PORT}`));
8. Chạy Server
Thêm vào package.json
:
Copy "scripts": {
"dev": "nodemon src/server.ts",
"build": "tsc",
"start": "node dist/server.js"
}
Chạy server:
9. Kiểm tra API
Dùng Postman hoặc cURL để thử nghiệm các API:
Lấy danh sách bài viết :
GET http://localhost:5000/api/posts
Tạo bài viết :
POST http://localhost:5000/api/posts
Copy {
"title": "Hello World",
"content": "Đây là bài viết đầu tiên!"
}
Lấy bài viết theo ID :
GET http://localhost:5000/api/posts/:id
Cập nhật bài viết :
PUT http://localhost:5000/api/posts/:id
Xóa bài viết :
DELETE http://localhost:5000/api/posts/:id
🎉 Kết luận
Bạn đã xây dựng thành công một API blog đơn giản sử dụng Node.js + TypeScript + MongoDB . Bạn có thể mở rộng bằng cách thêm xác thực (JWT), UI (React/Vue), hoặc tính năng bình luận! 🚀