Minimal Cloudflare Worker + Hono + Drizzle ORM (part 1)
Một dự án Cloudflare Worker Serverless tối giản, tương đương với Node.js, Express.js và Sequelize.
Khi bắt đầu với Cloudflare Workers, chúng ta thường rơi vào một tình huống khá quen thuộc: muốn dựng thật nhanh một worker nhỏ để thử routing, trả về response đơn giản...
Nhưng chỉ cần nghĩ đến số lượng file trong một template mặc định, một mớ cấu hình, cấu trúc file... là đã thấy hơi rối.
Trong những lúc như vậy, một project tối giản lại rất có giá trị. Chỉ cần đủ ít để nhìn ra luồng chạy của ứng dụng, nhưng cũng đủ rõ để sau này mở rộng tiếp.
Dự án này của mình một ví dụ như vậy.
Một dự án Cloudflare Worker Serverless tối giản, tương đương với Node.js, Express.js và Sequelize.
Trong Phần 1, chúng ta sẽ review initial commit đầu tiên của mình (đã chạy được), để rút ra câu trả lời cho câu hỏi quan trọng: cần những gì để spin up một Hono Worker thật đơn giản?
Initial Commit này đang có gì?
Commit đầu tiên tạo ra một bộ khung rất gọn, có thể hình dung như sau:
Trong đó, có 3 file quan trọng cần thiết để chạy worker đầu tiên:
Điểm hay của commit này là không cố làm nhiều việc cùng lúc. Nó chỉ giải quyết 2 endpoint rất cơ bản:
Vậy là đã đủ để thấy toàn bộ luồng của một Worker:
Hono Worker là gì, và vì sao cấu trúc này dễ học?
Trước khi đi vào code, mình chốt nhanh 3 khái niệm:
Cần tối thiểu những gì để spin up một Hono Worker?
Nếu chỉ muốn dựng một Hono Worker thật cơ bản, KHÔNG SỬ DỤNG TEMPLATE MẶC ĐỊNH CỦA CLOUDFLARE VỚI MỘT MỚ CODE TYPESCRIPT HỖN ĐỘN, bạn chỉ cần 4 phần.
1. Dependency
Trong package.json, initial commit chỉ cần:
Ý nghĩa rất đơn giản:
Với một Worker cực nhỏ, chừng này là đủ.
2. File cấu hình Wrangler
wrangler.toml trong initial commit cũng rất ngắn:
Ở đây cần chú ý 3 dòng:
Nếu thiếu main, Wrangler sẽ không biết bắt đầu từ đâu. Đây là một trong những cấu hình tối thiểu bắt buộc.
3. Entry point khởi tạo Hono app
Phần quan trọng nhất nằm ở src/index.ts:
Đây chính là bộ khung nhỏ nhất của app:
Nếu bạn muốn giản lược hơn nữa, thậm chí có thể viết tất cả trong một file:
Chỉ vậy là đã có một Hono Worker chạy được.
Và lúc này mặc dù đuôi file .ts vẫn chưa có types gì đáng chú ý.
4. Áp dụng mô hình code MVC
Bản Initial Commit tách route và controller ra 2 file riêng.
Sở dĩ mình làm vậy vì đã quen với mô hình MVC từ Express.js. Sau khi cài Drizzle ORM thì mình có thay đổi tên thư mục theo chuẩn của Drizzle.
Với project học tập hoặc proof of concept, đây là mức tách file vừa đủ đẹp.
4.1. Endpoint hello world: ví dụ nhỏ nhất nhưng rất cần thiết
Trong src/controllers/siteController.ts, route / được xử lý như sau:
Đây là ví dụ rất tốt cho người mới vì nó cho thấy 2 điều:
Khi mới spin up Worker, bạn gần như luôn nên có một endpoint kiểu này trước. Nó giúp kiểm tra:
Nói ngắn gọn: trước khi làm auth, database hay middleware, hãy để / trả về được một dòng text rõ ràng.
4.2 Endpoint thực tế hơn: trả về sitemap.xml
Điểm thú vị của initial commit là không dừng ở hello world, mà mình thêm luôn một bài toán thực tế nhỏ: sinh XML sitemap từ dữ liệu mẫu.
Cũng trong src/controllers/siteController.ts, route / được xử lý như sau:
Ở đây có vài điểm rất đáng học:
Phần này cho thấy một Hono Worker không chỉ dùng để trả JSON API. Nó hoàn toàn phù hợp cho những endpoint nhỏ như:
Đó là những use case rất hợp với Workers: nhỏ, rõ, chạy nhanh.
5. Model trong commit đầu tiên đơn giản đến mức nào?
src/models/sitemapModel.ts chỉ làm đúng một việc: đọc JSON và trả về dữ liệu đã có type.
Mô hình này hợp lý trong giai đoạn đầu vì:
Nó cũng phản ánh đúng tinh thần của initial commit: làm thứ nhỏ nhất có thể, nhưng vẫn giữ cấu trúc đủ sạch để mở rộng về sau.
Trong commit thứ 2, mình sẽ thêm Drizzle ORM cùng với các thao tác tương tự Sequelize: tạo mode, schema, method...
Mở rộng: thêm custom domain bằng code
Nếu bạn muốn gắn thêm custom domain cho Worker của mình, thì không cần cấu hình custom domain bằng thao tác tay rồi để đó, mà đưa thẳng cấu hình vào wrangler.toml:
Điều kiện là domain này của bạn phải nằm trong danh sách DNS trên Cloudflare, như vậy Cloudflare mới tự động cấu hình DNS phù hợp giúp bạn bằng code.
Ý nghĩa của phần này là:
Đây là một bước mở rộng rất thường gặp.
Nếu muốn tự dựng lại từ đầu, các bước ngắn gọn là gì?
Bạn có thể tóm tắt quy trình thành 5 bước:
Bước 1. Cài package
Bước 2. Tạo wrangler.toml
Bước 3. Tạo src/index.ts
Bước 4. Thêm script chạy local
Bước 5. Chạy app hoặc deply
Sau đó mở endpoint local mà Wrangler in ra, bạn sẽ thấy hello world.
Đó là phiên bản tối giản nhất của một Hono Worker.
Kết luận
Từ review commit Initial commit, mình nghĩ có thể rút ra một kết luận khá rõ: để spin up một Hono Worker thật đơn giản, bạn không cần quá nhiều thứ. Chỉ cần hono, wrangler, một file wrangler.toml, một src/index.ts, và một route đủ nhỏ để kiểm tra app đang chạy.
Phần còn lại là tổ chức code sao cho dễ hiểu. youhono chọn cách khá thân thiện với người từng dùng Express: tách routes, controllers, và models từ rất sớm, nhưng vẫn giữ project ở mức tối giản. Đây là một điểm khởi đầu đẹp nếu bạn muốn học Hono mà không bị ngợp.
Nếu đi tiếp từ đây, những bước tự nhiên kế tiếp sẽ là:
Nhưng trước tất cả những thứ đó, hãy chắc rằng bạn đã có một Worker nhỏ chạy ổn, hiểu được luồng request từ route đến response, và biết vì sao cấu trúc tối giản lại quan trọng. Initial Commit này làm khá tốt đúng điều đó.
