Xây Dựng Ứng Dụng Full-Stack TypeScript với NPM Workspaces

Xây dựng ứng dụng full-stack với TypeScript mang lại trải nghiệm phát triển tuyệt vời—type safety xuyên suốt codebase, shared interfaces giữa frontend và backend, và bắt lỗi tại compile-time. Trong hướng dẫn này, chúng ta sẽ xây dựng ứng dụng blog hoàn chỉnh sử dụng kiến trúc monorepo với NPM workspaces.
Những Gì Bạn Sẽ Học
✅ Thiết lập NPM workspaces monorepo
✅ Chia sẻ TypeScript types giữa frontend và backend
✅ Xây dựng REST API với Express.js và TypeScript
✅ Tạo React frontend với Vite
✅ Cấu hình TypeScript project references
✅ Workflow phát triển cho monorepos
✅ Production build và deployment setup
Điều Kiện Tiên Quyết
- Node.js v16+ và npm v7+ (workspaces yêu cầu npm 7+)
- Kiến thức TypeScript cơ bản từ TypeScript Giai Đoạn 1: Nền Tảng
- Kinh nghiệm React và Express.js cơ bản
📦 Full Source Code: Ví dụ hoàn chỉnh có sẵn trên GitHub: typescript-fullstack-demo
Ghi chú: Bài viết này chứa các ví dụ code tương tự phiên bản tiếng Anh. Chúng tôi tập trung vào giải thích khái niệm bằng tiếng Việt.
1. Tại Sao Monorepo với NPM Workspaces?
Vấn đề: Trong setup truyền thống, frontend và backend là các project riêng biệt với type definitions bị duplicate. Khi update backend API, bạn phải manually update frontend types—dễ lỗi và tốn thời gian.
Giải pháp: Monorepo với shared packages:
// packages/shared/src/types.ts (single source of truth)
export interface Post {
id: number;
title: string;
content: string;
}
// Dùng trong cả backend VÀ frontend
import { Post } from '@blog/shared';Lợi ích:
- Single source of truth cho types
- Atomic changes across packages
- Simplified dependency management
- Better code organization
2. Cấu Trúc Project
typescript-fullstack-demo/
├── packages/
│ ├── shared/ # Shared types và utilities
│ ├── server/ # Express.js backend
│ └── client/ # React + Vite frontend
├── package.json # Root workspace configuration
└── README.md3. Thiết Lập Monorepo
Root package.json:
{
"name": "typescript-fullstack-demo",
"private": true,
"workspaces": ["packages/*"],
"scripts": {
"dev": "concurrently \"npm run server\" \"npm run client\"",
"server": "npm run dev --workspace=@blog/server",
"client": "npm run dev --workspace=@blog/client",
"build": "npm run build --workspaces"
}
}4. Shared Package
Package chứa types được dùng bởi cả frontend và backend.
Key files:
packages/shared/src/types.ts- Common interfaces (Post, Comment, Category, ApiResponse)packages/shared/tsconfig.json- Vớicomposite: truecho project references
Types bao gồm:
Post,CreatePostRequest,UpdatePostRequestComment,CreateCommentRequestCategoryApiResponse<T>,PaginatedResponse<T>
5. Express.js Backend
Cấu trúc:
src/config/database.ts- SQLite setup với auto table creationsrc/models/Post.ts- Data model dùng types từ@blog/sharedsrc/controllers/postController.ts- Request handlers với typed responsessrc/routes/postRoutes.ts- API routessrc/index.ts- Server entry point
TypeScript config với project references:
{
"compilerOptions": {
"paths": {
"@blog/shared": ["../shared/src"]
}
},
"references": [{ "path": "../shared" }]
}API Endpoints:
GET /api/posts- Lấy tất cả postsGET /api/posts/:id- Lấy post theo IDGET /api/posts/search?q=query- Tìm kiếm postsPOST /api/posts- Tạo post mớiPUT /api/posts/:id- Update postDELETE /api/posts/:id- Xóa post
6. React Frontend với Vite
Cấu trúc:
src/services/api.ts- API service với typed responsessrc/components/PostList.tsx- Hiển thị danh sách postssrc/components/PostDetail.tsx- Chi tiết post với Markdown renderingsrc/App.tsx- Main app với routing
Vite config với proxy và alias:
export default defineConfig({
resolve: {
alias: {
'@blog/shared': path.resolve(__dirname, '../shared/src'),
},
},
server: {
port: 3000,
proxy: {
'/api': { target: 'http://localhost:5000' },
},
},
});Features:
- React Router cho client-side routing
- Axios cho HTTP requests với typed responses
- React Markdown với GitHub Flavored Markdown
7. Chạy Ứng Dụng
# Cài dependencies cho tất cả workspaces
npm install
# Build shared package trước
npm run build --workspace=@blog/shared
# Development mode (cả frontend và backend)
npm run dev
# Production build
npm run build
npm start8. Lợi Ích Chính
Type Safety Across the Stack: Khi thay đổi type trong @blog/shared, TypeScript ngay lập tức bắt lỗi trong cả frontend và backend.
Single Dependency Installation: Một npm install ở root xử lý mọi thứ.
Consistent Tooling: Share configurations across packages (ESLint, Prettier, TypeScript).
9. Workspace Commands Reference
# Install dependency trong specific workspace
npm install axios --workspace=@blog/client
# Run script trong specific workspace
npm run dev --workspace=@blog/server
# Run script trong tất cả workspaces
npm run build --workspaces
# List tất cả workspaces
npm ls --workspaces10. Troubleshooting
Types Not Updating: Rebuild shared package
npm run build --workspace=@blog/sharedModule Not Found: Reinstall từ root
rm -rf node_modules packages/*/node_modules
npm installSummary
Trong hướng dẫn này, bạn đã học:
✅ Thiết lập NPM workspaces monorepo structure
✅ Tạo shared TypeScript packages cho type safety
✅ Xây dựng REST API với Express.js và TypeScript
✅ Tạo React frontend với Vite
✅ Cấu hình TypeScript project references
✅ Development và production workflows
✅ Troubleshooting common monorepo issues
Kiến trúc này scale tốt—bạn có thể thêm shared packages (@blog/utils, @blog/validation) và type safety tự động extends.
Bước Tiếp Theo
Giờ bạn đã có full-stack TypeScript monorepo, khám phá:
Mở Rộng Ứng Dụng:
- Thêm user authentication với JWT
- Implement pagination và filtering
- Thêm image upload functionality
- Deploy với Docker
Học Thêm:
- TypeScript Giai Đoạn 2: Frontend Development - Advanced React patterns
- JavaScript Build Tools & Bundlers Explained - Hiểu cách Vite hoạt động
- NPM Workspaces: Monorepo vs Polyrepo - Deep dive vào monorepo architecture
- Express.js vs Fastify - So sánh Node.js frameworks
Thuộc chuỗi bài Lộ Trình Học TypeScript
📬 Đăng ký nhận bản tin
Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.
Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.
💬 Comments
Đăng nhập để bình luận
Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.