Deploy Go lên Vercel và làm ứng dụng hóng hớt
Trước tiên, là nội dung chính đúng như tiêu đề:
Có thể bạn biết rồi, ngoài JavaScript, TypeScript, NodeJS, Next.js các kiểu ra thì Vercel còn hỗ trợ deploy cả Go nữa.
Mặc định code được deploy trên Vercel sẽ sử dụng môi trường Node.js, nhưng nếu Vercel detect được file go.mod
trong project root của bạn, thì nó sẽ chuyển qua Go runtime. Mỗi một file *.go
trong thư mục /api
của bạn sẽ là một API endpoint (với điều kiện là file đó có export một function kiểu HandlerFunc).
Ví dụ với cấu trúc thư mục sau:
.
├── api
│ ├── foo.go -----> your-app.com/api/foo
│ └── bar.go -----> your-app.com/api/bar
└── go.mod
Lưu ý là các endpoint này có thể được request với bất kỳ method gì, nếu muốn giới hạn từng method với từng endpoint cụ thể thì bạn phải kiểm tra trong handler function:
// POST /api/foo --> 200 OK
// GET /api/foo --> 405 Method Not Allowed
func FooHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
fmt.Fprintf(w, "OK")
}
Rồi thế là xong phần nội dung chính. Ngắn gọn dễ hiểu, tuy nhiên bài ngắn quá, không vui tí nào. Hãy thử ứng dụng kiến thức này để làm một cái gì đó vui vẻ tí xem sao.
Chúng ta sẽ build một trang web tự động hiển thị các comment mới nhất trên Hacker News, vì nếu như Giáng sinh này, bạn chỉ có một mình và không đi đâu (không như mình, lúc các bạn đọc được bài này thì mình đang trên đường lái xe đi nghỉ lễ rồi 😏), thì có thể dùng nó để xem thiên hạ đang bàn tán gì, mình đặt tên cho nó là Hacker Live cho dễ hình dung.
Tạo một thư mục mới, init Go module rồi tạo file với cấu trúc như sau:
$ go mod init huy.rocks/hackerlive
$ mkdir api && touch api/feed.go
$ touch index.html
.
├── api
│ └── feed.go
├── go.mod
└── index.html
Cơ chế hoạt động của Hacker Live được mô tả qua sơ đồ sau:
Chúng ta sẽ có một API endpoint tên là /api/feed
có nhiệm vụ fetch các comment mới nhất trên Hacker News về, dữ liệu comment chúng ta lấy từ RSS feed (https://hnrss.org/newcomments).
// api/feed.go
func FeedHandler(w http.ResponseWriter, r *http.Request) {
// Fetch RSS feed từ Hacker News
resp := http.Get("https://hnrss.org/newcomments")
defer resp.Body.Close()
// Parsing
var feed RSSFeed
xml.NewDecoder(resp.Body).Decode(&feed)
// Return về client
...
}
Phần UI, để cho tiện thì chúng ta sẽ dùng htmx, giới thiệu nhanh gọn thì đây là một thư viện cho phép chúng ta sử dụng rất nhiều những tính năng của trình duyệt như AJAX, WebSocket, Form Validation,... mà không cần viết tí JavaScript nào. Cụ thể, ở đây chúng ta chỉ cần dùng hx-get
để fetch nội dung từ /api/feed
, và hiện nó lên trang.
<!-- index.html -->
<html>
<head>
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
</head>
<body>
<h1>Hacker Live</h1>
<div hx-get="/api/feed"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
Loading...
</div>
</body>
</html>
Trong đoạn HTML trên, hx-trigger="load, every 30s"
nghĩa là chúng ta bắt đầu fetch dữ liệu khi trang web vừa được load lên, sau đó cứ mỗi 30 giây thì fetch lại một lần. Dòng chữ "Loading..." sẽ được thay thế bằng nội dung trả về từ API.
Ở phía API, thay vì trả về JSON thì chúng ta chỉ cần trả về HTML trực tiếp, code Go nhưng tâm hồn PHP:
// api/feed.go
func FeedHandler(w http.ResponseWriter, r *http.Request) {
...
// Return về client
w.Header().Set("Content-Type", "text/html")
for _, item := range feed.Items {
fmt.Fprintf(w, `
<div class="feed-item">
<h3><a href="%s">%s</a></h3>
<div class="meta">
by %s • %s
</div>
<div class="description">%s</div>
</div>
`, item.Link, item.Title,
item.Creator, item.PubDate,
item.Description
)
}
}
Rồi, giờ thì chỉ việc deploy lên Vercel:
$ vercel deploy
Và thế là, tèn ten, có ngay một ứng dụng để ngồi FOMO: https://hackerlive.vercel.app/
Trong bài có lược bỏ đi một phần code, các bạn có thể tham khảo source code đầy đủ tại https://github.com/huytd/hacker-live