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.
Những gì đã học: Javascript, Node.js, Express.js, Sequelize Những gì sẽ áp dụng: Typescrypt, Node.js Compat trên Cloudflare Worker, Hono, Drizzle ORM 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:
package.json để khai báo dependency và script chạy app wrangler.toml để Cloudflare biết entry point của Worker src/index.ts làm nơi khởi tạo Hono app Đ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:
/sitemap.xml trả về XML sitemap Vậy là đã đủ để thấy toàn bộ luồng của một Worker:
request đi vào src/index.ts route được mount từ siteRoutes controller nhận Context của Hono controller trả về response text hoặc XML với route sitemap, dữ liệu được lấy từ model 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:
Cloudflare Worker là môi trường chạy JavaScript/TypeScript ở edge, phù hợp cho các endpoint nhỏ, nhanh, không cần dựng nguyên một server truyền thống. Hono là web framework rất gọn cho Workers và nhiều runtime khác. Nó lo phần routing, request context, response helper... Wrangler là CLI và công cụ cấu hình để chạy local, deploy, và kết nối project với Cloudflare Workers. 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:
wrangler để chạy local và deploy dev để bật môi trường local deploy để đẩy Worker lên Cloudflare 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:
compatibility_date: mốc tương thích runtime của Cloudflare 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:
export app mặc định để Worker runtime sử dụng 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:
Hono truyền vào một Context c.text() là cách nhanh nhất để trả về plain text response 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:
app đã boot thành công chưa Wrangler local có map request đúng không 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:
dữ liệu không hard-code trong controller mà đi qua model XML được build bằng template string, đủ đơn giản để đọc response trả về Content-Type: application/xml 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ì:
không phát sinh async hoặc query phức tạp người mới vẫn nhìn rõ ranh giới giữa controller và data layer 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à:
[[routes]] khai báo một route mapping cho Worker pattern là domain hoặc pattern mà Worker sẽ phục vụ custom_domain = true cho biết đây là custom domain, không phải route wildcard kiểu truyền thống Đâ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à:
thêm type cho environment bindings chuyển dữ liệu tĩnh sang D1 hoặc KV thêm auth hoặc middleware chuẩn hóa cấu trúc cho nhiều route hơn 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 đó.