Giới thiệu dự án
Thói quen đọc sách và tiếp cận tri thức tại Việt Nam đang trải qua giai đoạn chuyển dịch số mạnh mẽ. Báo cáo từ Hiệp hội Xuất bản Việt Nam ghi nhận hơn 50 triệu độc giả trong nước với mức tăng trưởng 10% qua từng năm. Tuy nhiên, tỉ lệ đọc sách trung bình trên đầu người vẫn còn khiêm tốn so với khu vực, phần lớn do sự cạnh tranh khốc liệt từ các nền tảng giải trí trực tuyến và rào cản về tính tiện lợi, chi phí cũng như phương thức đọc truyền thống.
Đề tài tốt nghiệp "Xây dựng Website Đọc Sách Mori Sử Dụng Next.js và Node.js" được thực hiện bởi nhóm tác giả tại Khoa Công nghệ Thông tin – Trường Đại học Sư phạm Kỹ thuật TP.HCM (HCMUTE), dưới sự hướng dẫn của TS. Huỳnh Xuân Phụng. Dự án giải quyết trực tiếp bài toán số hóa văn hóa đọc bằng cách xây dựng nền tảng phân phối sách điện tử (Ebook) kết hợp sách nói (Audiobook) và mạng xã hội chia sẻ góc nhìn đọc sách đa chiều.
+-----------------------------------------------------------------------------+
| MORI ECOSYSTEM |
+-----------------------------------------------------------------------------+
| [ Web Client (Next.js 14) ] <---> [ REST API Gateway (Express / Node.js) ]|
| [ Admin Dashboard (React) ] <---> [ NLP Moderation Microservice (Python) ]|
+-----------------------------------------------------------------------------+
|
+-------------------+-------------------+
| |
[ MongoDB Cluster 7.0 ] [ Cloud Object Storage ]
(BSON Data / Document Store) (EPUB, MP3, Cover Assets)
Vấn đề thực tiễn và điểm nghẽn (Pain Points)
- Thiếu tính tương tác cộng đồng: Đa phần các website đọc sách truyền thống chỉ hoạt động như một kho chứa file PDF/EPUB đơn thuần, thiếu tính năng mạng xã hội (bình luận, review, theo dõi tác giả, thiết lập mục tiêu).
- Trải nghiệm tiếp cận hạn chế: Người dùng khiếm thị hoặc người bận rộn gặp khó khăn khi tiếp cận Ebook dạng text thuần túy do thiếu khả năng chuyển đổi tức thời giữa Text-to-Speech (TTS) và sách nói chuẩn.
- Hiệu năng và bảo mật: Hệ thống phân phối nội dung số thường gặp hiện tượng tải trang chậm (Client-Side Rendering nặng), thiếu cơ chế kiểm duyệt nội dung độc hại tự động và quản lý giao dịch bản quyền chưa tối ưu.
Mục tiêu dự án
- Mục tiêu công nghệ: Xây dựng kiến trúc full-stack hiện đại kết hợp SSR/SSG từ Next.js 14 và RESTful API bất đồng bộ hiệu năng cao trên nền tảng Node.js 20 LTS, Express.js 4.19 và MongoDB 7.0.
- Mục tiêu quy trình: Ứng dụng quy trình phát triển Agile/Scrum phân tách thành các Sprint 2 tuần, kết hợp hệ thống kiểm thử tự động (Jest, Selenium WebDriver) và pipeline CI/CD với Docker và GitHub Actions.
- Mục tiêu sản phẩm: Triển khai đầy đủ 34 chức năng nghiệp vụ, bao gồm E-reader đa chế độ, Audio player, quản lý gói hội viên/mua lẻ, mạng xã hội mini và bộ lọc bình luận thông minh bằng AI/NLP.
Phạm vi và giới hạn hệ thống
- Phạm vi áp dụng: Nền tảng web tương thích trên Desktop, Tablet và Mobile; phục vụ độc giả phổ thông, độc giả khiếm thị và các quản trị viên phân phối nội dung số.
- Giới hạn kỹ thuật: Chưa tích hợp bộ thanh toán cổng quốc tế (chỉ hỗ trợ mô hình ví điện tử/Voucher nội địa) và chưa hỗ trợ đọc offline hoàn toàn ở chế độ PWA chuyên sâu.
Phân tích và thiết kế giải pháp
Phân tích hiện trạng
Khảo sát thực tế các nền tảng đọc sách phổ biến tại thị trường Việt Nam và quốc tế xác định các ưu/nhược điểm cốt lõi:
| Tiêu chí |
Mori Platform |
Waka.vn |
Sachtot.vn |
Wattpad |
| Công nghệ Frontend |
Next.js 14 (SSR / SSG) |
Single Page App |
Web CMS truyền thống |
React / Native App |
| Chuyển đổi Text-to-Speech |
Tích hợp sẵn (Realtime TTS) |
Chỉ có trên App Mobile |
Không hỗ trợ |
Không hỗ trợ |
| Tính năng Mạng xã hội |
Đầy đủ (Bài viết, Like, Share, Goal) |
Hạn chế (Review ngắn) |
Không hỗ trợ |
Rất mạnh (Cộng đồng tác giả) |
| Kiểm duyệt AI / NLP |
Tự động phân loại bình luận độc hại |
Duyệt thủ công |
Duyệt thủ công |
Báo cáo vi phạm thủ công |
| Chi phí tiếp cận |
Đọc miễn phí + Mua lẻ + Hội viên |
Thu phí gói định kỳ cao |
Miễn phí (sách cũ) |
Freemium kèm quảng cáo |
Phân loại yêu cầu người dùng theo mô hình MoSCoW
- Must-have: Đăng ký/đăng nhập JWT, đọc Ebook đa chế độ (Dark/Light Mode), trình phát Audiobook, tìm kiếm sách theo bộ lọc đa chiều, quản lý giỏ hàng và thanh toán.
- Should-have: Tính năng Text-to-Speech tự động, mạng xã hội mini (bài viết, bình luận, tương tác), theo dõi tác giả, thiết lập mục tiêu đọc cá nhân.
- Could-have: Bộ lọc bình luận toxic sử dụng mô hình NLP, mã giảm giá (Voucher), chia sẻ chứng nhận thành tích lên Facebook Open Graph.
- Won't-have (giai đoạn này): Trình biên tập trực tuyến chuẩn WYSIWYG nâng cao dành cho tác giả tự xuất bản sách bản quyền.
Thiết kế hệ thống
Hệ thống được thiết kế theo mô hình kiến trúc phân lớp hướng dịch vụ (Service-Oriented Tiered Architecture):
+------------------------------------------------------------------------------------+
| PRESENTATION TIER |
| Next.js Client (Port 3000) | Admin Dashboard (Port 3001) | Tailwind CSS |
+------------------------------------------------------------------------------------+
│ HTTPS / JSON RESTful
+------------------------------------------------------------------------------------+
| APPLICATION TIER |
| Node.js + Express.js API Gateway (Port 5000) |
| ├── Auth Controller (JWT / Bcrypt) ├── Reading Goal & Analytics Service |
| ├── Book & E-Reader Engine ├── NLP Moderation Engine (FastAPI micro)|
| └── Payment & Voucher Manager ├── Storage Provider (Local / S3) |
+------------------------------------------------------------------------------------+
│ Mongoose ODM / TCP Socket
+------------------------------------------------------------------------------------+
| DATA TIER |
| MongoDB Cluster 7.0 (Collections: Accounts, Books, Transactions, Reviews, Goals) |
+------------------------------------------------------------------------------------+
Bảng thông số công nghệ chi tiết
| Thành phần |
Công nghệ / Thư viện |
Phiên bản |
Vai trò kỹ thuật |
| Frontend Web |
Next.js / React |
14.2.x / 18.2 |
Server-Side Rendering, tối ưu Core Web Vitals |
| Backend Runtime |
Node.js / Express.js |
20.11 LTS / 4.19 |
Xử lý logic nghiệp vụ bất đồng bộ, routing |
| Database Engine |
MongoDB Community |
7.0.x |
Lưu trữ dữ liệu tài liệu linh hoạt (NoSQL) |
| Unit Testing |
Jest / Supertest |
29.7.x / 6.3 |
Kiểm thử đơn vị logic API và Mock controller |
| E2E Testing |
Selenium WebDriver |
4.18.x |
Kiểm thử tự động luồng giao diện người dùng |
| Container & CI |
Docker / GitHub Actions |
26.0 / v4 |
Đóng gói môi trường và tự động hóa quy trình CI/CD |
Thiết kế cơ sở dữ liệu (Database Schema)
Dữ liệu được tổ chức dưới dạng các Collection BSON chuẩn trong MongoDB, tối ưu hóa khả năng đánh chỉ mục (Index) trên các trường truy vấn thường xuyên:
// Cấu trúc Schema bảng Book trong MongoDB (Mongoose)
const BookSchema = new mongoose.Schema({
title: { type: String, required: true, index: true },
author: { type: String, required: true, index: true },
category_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
tags: [{ type: String, index: true }],
description: { type: String },
cover_image: { type: String, required: true },
content_url: { type: String, required: true }, // Đường dẫn file EPUB/PDF
audio_url: { type: String }, // Đường dẫn file MP3/Audio
price: { type: Number, default: 0 },
is_membership: { type: Boolean, default: false },
view_count: { type: Number, default: 0 },
rating_avg: { type: Number, default: 0.0 },
created_at: { type: Date, default: Date.now }
});
BookSchema.index({ title: "text", author: "text", tags: "text" });
Danh mục API Endpoints tiêu biểu
| Phương thức |
Endpoint |
Chức năng |
Phân quyền |
POST |
/api/v1/auth/login |
Xác thực người dùng và cấp JWT Token |
Public |
GET |
/api/v1/books/:id |
Lấy thông tin chi tiết và nội dung sách |
Public / User |
POST |
/api/v1/reviews |
Tạo bài đánh giá sách kèm số sao |
User |
POST |
/api/v1/nlp/moderate-comment |
Kiểm tra nội dung bình luận qua AI |
Internal Service |
POST |
/api/v1/transactions/checkout |
Xử lý giao dịch mua sách / gia hạn gói |
User |
GET |
/api/v1/admin/analytics/revenue |
Thống kê doanh thu theo tháng |
Administrator |
Phương pháp nghiên cứu và phát triển
Dự án áp dụng khung làm việc Agile/Scrum xuyên suốt vòng đời phát triển:
- Kế hoạch Sprint: Chia làm 5 Sprint chính (mỗi Sprint 2 tuần) từ khâu khảo sát nghiệp vụ, thiết kế Class/Sequence Diagram, xây dựng API Server, hoàn thiện giao diện Next.js đến kiểm thử tích hợp.
- Đánh giá rủi ro (Risk Assessment): Xử lý rủi ro mất cân bằng tải bộ nhớ do cơ chế Caching của MongoDB bằng cách định tuyến RAM hợp lý; giải quyết vấn đề độ trễ xử lý NLP bằng cách tách microservice chạy trên cổng riêng biệt.
Triển khai và kết quả thực nghiệm
Quá trình phát triển và hiện thực hóa mã nguồn
Mã nguồn được phân tách module rõ ràng, áp dụng Clean Code và Middleware Pattern trên Express.js:
// Middleware xác thực quyền truy cập và kiểm tra Token JWT
const authMiddleware = async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).json({ success: false, message: "Truy cập bị từ chối. Token không tồn tại." });
}
const token = authHeader.split(" ")[1];
const decoded = jwt.verify(token, process.env.JWT_SECRET_KEY);
req.user = decoded;
next();
} catch (error) {
return res.status(403).json({ success: false, message: "Token không hợp lệ hoặc đã hết hạn." });
}
};
Quy trình lọc bình luận độc hại tự động được tích hợp trước khi ghi dữ liệu vào Collection Comments:
// Xử lý kiểm duyệt bình luận bằng mô hình NLP trước khi lưu
const postCommentHandler = async (req, res) => {
const { bookId, content, rating } = req.body;
const userId = req.user.id;
// Gửi nội dung tới Microservice NLP để phân loại nhãn
const nlpResponse = await axios.post(`${process.env.NLP_SERVICE_URL}/predict`, { text: content });
const isSpamOrToxic = nlpResponse.data.is_toxic;
const newComment = await Comment.create({
book_id: bookId,
user_id: userId,
content,
rating,
status: isSpamOrToxic ? 'PENDING_REVIEW' : 'APPROVED'
});
return res.status(201).json({ success: true, data: newComment, flagged: isSpamOrToxic });
};
Kiểm thử và đánh giá hệ thống
Hệ thống được kiểm thử tự động toàn diện qua hai tầng: Kiểm thử đơn vị (Unit Testing) với Jest và Kiểm thử chức năng giao diện tự động (E2E Testing) với Selenium WebDriver.
// Kịch bản Unit Test cho API Review sách bằng Jest và Supertest
describe("POST /api/v1/reviews - Kiểm thử chức năng đánh giá sách", () => {
it("Nên trả về mã lỗi 400 nếu điểm đánh giá không nằm trong khoảng 1-5 sao", async () => {
const response = await request(app)
.post("/api/v1/reviews")
.set("Authorization", `Bearer ${mockValidToken}`)
.send({
bookId: "64f8a92b1c2e4f0012a9b341",
content: "Cuốn sách rất ý nghĩa!",
rating: 6 // Điểm không hợp lệ
});
expect(response.status).toBe(400);
expect(response.body.success).toBe(false);
expect(response.body.message).toContain("Rating must be between 1 and 5");
});
});
Kết quả kiểm thử tự động
PASS tests/unit/auth.test.js
PASS tests/unit/books.test.js
PASS tests/unit/reviews.test.js
PASS tests/unit/transactions.test.js
----------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------------|---------|----------|---------|---------|-------------------
All files | 92.45 | 86.66 | 91.17 | 93.10 |
controllers/auth.js | 95.12 | 90.00 | 100.0 | 95.12 | 45-47
controllers/book.js | 90.38 | 83.33 | 88.88 | 91.48 | 112,145-148
controllers/review.js | 93.75 | 88.23 | 100.0 | 94.59 | 78-80
----------------------|---------|----------|---------|---------|-------------------
Test Suites: 4 passed, 4 total
Tests: 28 passed, 28 total
Snapshots: 0 total
Time: 3.421 s
Tự động hóa E2E bằng Selenium
Kịch bản kiểm thử Selenium mô phỏng 100% các luồng người dùng cốt lõi: Đăng ký -> Tìm sách -> Bật Dark Mode -> Đọc sách trực tuyến -> Thêm ghi chú -> Mua gói cước. Toàn bộ 16 kịch bản kiểm thử giao diện đều ghi nhận kết quả thành công với thời gian phản hồi trung bình của mỗi thao tác < 1.2s.
Kết quả đạt được đối chiếu với mục tiêu
+-----------------------------------------------------------------------------+
| FEATURE COMPLETION MATRIX (34/34) |
+-----------------------------------------------------------------------------+
| [X] User Authentication (JWT) [X] Audio Player Streaming |
| [X] Dynamic E-Reader (Font/Theme) [X] NLP Comment Filter Integration |
| [X] Reading Goal Progress Tracker [X] Admin Revenue & Book Management |
| [X] Voucher Discount Engine [X] CI/CD Automated Deployment |
+-----------------------------------------------------------------------------+
- Tốc độ phản hồi trung bình (API Response Time):
~145ms đối với các truy vấn đọc dữ liệu sách thông thường có đánh Index trên MongoDB.
- Điểm số Lighthouse Performance: Đạt
94/100 điểm hiệu năng trên máy tính bảng và desktop nhờ cơ chế tối ưu hóa hình ảnh và nén Server-Side Rendering của Next.js.
- Tỉ lệ bao phủ mã nguồn (Code Coverage): Đạt
92.45% trên toàn bộ các controller nghiệp vụ backend.
Đổi mới và đóng góp
- Kiến trúc đọc sách lai (Hybrid Ebook-to-Speech Streaming): Khắc phục điểm yếu của các web đọc sách thông thường bằng việc cho phép người đọc chuyển đổi liền mạch từ dạng văn bản sang giọng đọc tự động tại vị trí trang đang đọc dở mà không làm mất dấu tiến trình.
- Cơ chế lọc nội dung độc hại ứng dụng NLP: Giải quyết triệt để vấn đề quá tải của quản trị viên khi phải duyệt hàng ngàn bình luận; hệ thống tự động gắn cờ và phân loại các nội dung tiêu cực, thù địch với độ chính xác đạt trên
88%.
- Mô hình hóa động lực học đọc sách (Gamification Reading Goals): Tích hợp công cụ thiết lập mục tiêu đọc theo tuần/tháng, tính toán phần trăm hoàn thành theo thời gian thực và tự động tạo chứng chỉ số để chia sẻ trực tiếp lên các mạng xã hội.
+-----------------------------------------------------------------------------+
| HIỆU QUẢ CẢI TIẾN HỆ THỐNG |
+-----------------------------------------------------------------------------+
| Thời gian tải trang ban đầu (Next.js SSG): Giảm 42% so với React SPA |
| Tốc độ xử lý truy vấn dữ liệu (MongoDB Index): Tăng 3.5 lần so với SQL |
| Khối lượng công việc duyệt bình luận thủ công: Giảm 68% nhờ AI/NLP |
+-----------------------------------------------------------------------------+
Ứng dụng thực tế và triển khai
Kịch bản triển khai thực tế
Nền tảng Mori được thiết kế sẵn sàng để ứng dụng tại các thư viện trường đại học, nhà xuất bản sách điện tử hoặc các đơn vị phát triển văn hóa đọc cộng đồng:
- Kịch bản 1 - Thư viện số đại học: Quản lý hàng chục ngàn tài liệu nội bộ, cho phép sinh viên mượn và đọc sách số theo tài khoản sinh viên đã xác thực.
- Kịch bản 2 - Doanh nghiệp phát hành sách: Triển khai bán Ebook kèm mã giảm giá linh hoạt, phân phối gói thuê bao định kỳ (Monthly Subscription).
Chiến lược đóng gói và CI/CD Pipeline
Ứng dụng được container hóa hoàn toàn bằng Docker với cấu hình Multi-stage build nhằm giảm thiểu dung lượng image và tăng cường bảo mật:
# Multi-stage Dockerfile cho Backend Node.js API
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 5000
USER node
CMD ["node", "server.js"]
Quy trình tự động hóa GitHub Actions đảm bảo mỗi commit lên nhánh main đều phải vượt qua bộ kiểm thử Jest trước khi build và deploy tự động:
# .github/workflows/deploy.yml
name: Mori Platform CI/CD Workflow
on:
push:
branches: [ main ]
jobs:
test-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Run Jest Unit Tests
run: npm run test:coverage
- name: Build Docker Image
run: docker build -t mori-backend:latest .
Hạn chế và hướng phát triển
Hạn chế kỹ thuật hiện tại
- Tính năng Text-to-Speech phụ thuộc một phần vào Web Speech API của trình duyệt người dùng, dẫn đến chất lượng giọng đọc chưa đồng nhất trên một số hệ điều hành cũ.
- Chưa hỗ trợ chế độ đọc PWA offline đồng bộ hai chiều khi mất kết nối mạng hoàn toàn.
Hướng phát triển tương lai
- Thuật toán gợi ý cá nhân hóa (Recommendation System): Tích hợp mô hình Collaborative Filtering hoặc Matrix Factorization dựa trên lịch sử đọc và đánh giá của từng cá nhân.
- Tích hợp mô hình ngôn ngữ lớn (LLM / RAG): Bổ sung tính năng trợ lý ảo tóm tắt nội dung chương sách và giải đáp thắc mắc của độc giả theo ngữ cảnh cuốn sách.
- Mở rộng thanh toán: Tích hợp các cổng thanh toán VNPAY, MoMo và Stripe để phục vụ độc giả quốc tế.
Đối tượng hưởng lợi
+-----------------------------------------------------------------------------+
| BENEFICIARY ECOSYSTEM |
+-----------------------------------------------------------------------------+
| [ SINH VIÊN ] -> Môi trường đọc sách trực quan, tra cứu nhanh, |
| tự theo dõi lộ trình và mục tiêu học tập. |
| [ LẬP TRÌNH VIÊN ] -> Nguồn tài liệu tham khảo chuẩn mực về kiến trúc |
| Next.js + Node.js, Jest Test, CI/CD Pipeline. |
| [ NHÀ XUẤT BẢN ] -> Nền tảng số hóa kênh bán lẻ Ebook/Audiobook, |
| tối ưu doanh thu và quản lý bản quyền minh bạch. |
| [ NHÀ NGHIÊN CỨU ] -> Case-study thực tế về ứng dụng NLP trong kiểm duyệt |
| nội dung và kiến trúc ứng dụng web hướng hiệu năng. |
+-----------------------------------------------------------------------------+
Câu hỏi thường gặp
1. Yêu cầu phần cứng và môi trường để triển khai hệ thống là gì?
Máy chủ tối thiểu cần 2 vCPU, 4GB RAM, cài đặt sẵn Docker Engine 24.0+ và Docker Compose. Đối với database, khuyến nghị sử dụng cụm MongoDB Atlas hoặc VPS Linux Ubuntu 22.04 LTS riêng biệt để đảm bảo hiệu suất I/O ổ đĩa SSD.
2. Hệ thống xử lý bài toán quá tải khi nhiều người cùng đọc sách như thế nào?
Nhờ kiến trúc Single-Thread Event Loop non-blocking I/O của Node.js kết hợp với cơ chế Static Site Generation (SSG) và Incremental Static Regeneration (ISR) từ Next.js, các trang chi tiết sách được cache tĩnh tại CDN/Server, giảm đến 80% truy vấn trực tiếp vào cơ sở dữ liệu MongoDB.
3. Quy trình bảo vệ bản quyền sách điện tử trên website hoạt động ra sao?
Các file nội dung số (EPUB/PDF) không được cung cấp link tải trực tiếp mà được lưu trữ trên Object Storage có mã hóa đường dẫn (Signed URL có thời hạn). Trình đọc E-reader render dữ liệu theo từng phân đoạn vào DOM và vô hiệu hóa các phím tắt sao chép nội dung trái phép.
4. Chi phí duy trì hệ thống ước tính hàng tháng là bao nhiêu?
Với quy mô khởi điểm khoảng 10.000 người dùng hoạt động hàng tháng (MAU), chi phí duy trì bao gồm VPS Server ($15 - $20/tháng), MongoDB Atlas ($10 - $25/tháng) và CDN/Storage ($5 - $10/tháng), tổng ngân sách ước tính chỉ dao động từ 700.000 VNĐ đến 1.300.000 VNĐ/tháng.
5. Làm thế nào để tích hợp thêm các thể loại sách nói định dạng bitrate cao?
Hệ thống hỗ trợ chuẩn lưu trữ media qua chunk streaming. Quản trị viên chỉ cần upload file âm thanh chuẩn MP3/AAC qua trang quản trị Admin, backend sẽ tự động phân tách và phát luồng qua giao thức HTTP Range Requests tối ưu hóa băng thông.
Kết luận
Đề tài tốt nghiệp "Xây dựng Website Đọc Sách Mori Sử Dụng Next.js và Node.js" của sinh viên Nguyễn Thị Bích Liên và Phạm Quỳnh Hương đã giải quyết trọn vẹn bài toán xây dựng một nền tảng đọc sách trực tuyến hiện đại, giàu tính tương tác và có khả năng mở rộng cao. Bằng việc kết hợp sức mạnh render tối ưu của Next.js 14, khả năng xử lý bất đồng bộ của Node.js/Express, tính linh hoạt của MongoDB và quy trình kiểm thử tự động nghiêm ngặt bằng Jest và Selenium, dự án không chỉ hoàn thành xuất sắc các yêu cầu kỹ thuật mà còn đóng góp một giải pháp thực tiễn có giá trị cao cho quá trình chuyển đổi số văn hóa đọc tại Việt Nam.