Kapybara
Published on

Hướng dẫn triển khai bình luận với Cloudflare Worker và D1 Database

Authors
  • avatar
    Name
    Khoa (kapybara)
    Occupation
    Full-stack developer

Trong thế giới công nghệ phát triển nhanh chóng, serverless là một xu hướng nổi bật vì tính năng linh hoạt, tiết kiệm chi phí và khả năng mở rộng. Đặc biệt, với nhu cầu giảm tải máy chủ và tiết kiệm chi phí, các giải pháp hosting miễn phí trở thành ưu tiên hàng đầu cho các nhà phát triển. Trong bài viết này, chúng ta sẽ khám phá cách triển khai một hệ thống bình luận sử dụng Cloudflare WorkerD1 Database để tạo nên một nền tảng serverless dễ dàng quản lý và tối ưu chi phí.

Vì sao chọn serverless?

Thông thường, việc lưu trữ và quản lý dữ liệu đòi hỏi một máy chủ vật lý hoặc máy ảo, dẫn đến chi phí cao và phức tạp trong vận hành. Với serverless, nhà phát triển chỉ cần tập trung vào code và logic ứng dụng mà không cần lo lắng về cơ sở hạ tầng máy chủ. Điều này cũng có nghĩa là bạn chỉ trả phí dựa trên lượng truy cập và tài nguyên sử dụng, thay vì chi phí cố định.

Một số lợi ích của serverless:

  • Chi phí thấp: Không cần phải chi trả cho máy chủ khi không có người dùng truy cập.
  • Tính mở rộng dễ dàng: Ứng dụng tự động mở rộng dựa trên nhu cầu thực tế.
  • Dễ bảo trì: Tập trung vào phát triển và nâng cấp tính năng, không cần lo lắng về máy chủ.

Tổng quan về Cloudflare Worker và D1 Database

Cloudflare Worker là một giải pháp serverless do Cloudflare cung cấp, cho phép bạn triển khai các ứng dụng JavaScript trực tiếp tại biên của mạng lưới, từ đó rút ngắn thời gian tải và xử lý. Còn D1 Database là một sản phẩm cơ sở dữ liệu quan hệ (database relational) mới của Cloudflare, cung cấp một giải pháp lưu trữ dữ liệu thân thiện cho các ứng dụng serverless.

Bước 1: Cài đặt môi trường

Để bắt đầu, bạn cần tạo một tài khoản Cloudflare (miễn phí) và cài đặt Wrangler, công cụ CLI chính thức của Cloudflare để triển khai Workers.

# Cài đặt Wrangler CLI
npm install -g wrangler
# Đăng nhập vào tài khoản Cloudflare
wrangler login

#hoặc
npx wrangler login

Sau khi đăng nhập, bạn đã sẵn sàng để tạo một Worker mới.

Bước 2: Tạo Worker cho tính năng bình luận

Khởi tạo dự án Worker

# Tạo dự án Worker mới
npm create cloudflare@latest -- my-comment
#hoặc
yarn create cloudflare@latest my-comment

Sau khi chạy lệnh trên các bạn chọn theo các bước sau:

  • For What would you like to start with?, choose Hello World example.
  • For Which template would you like to use?, choose Hello World Worker.
  • For Which language do you want to use?, choose TypeScript.
  • For Do you want to use git for version control?, choose Yes.
  • For Do you want to deploy your application?, choose No (Chúng ta sẽ cần thay đổi vài thứ trước khi deploy).

Sau khi setup xong các bạn sẽ được một thư mục như này.

Cấu hình Worker

Trong thư mục dự án, mở file wrangler.toml và cập nhật thông tin cấu hình để kết nối với D1 Database:

#:schema node_modules/wrangler/config-schema.json
name = "my-comment"
main = "src/index.ts"
compatibility_date = "2024-11-12"
compatibility_flags = ["nodejs_compat"]

[[d1_databases]]
#sẽ được tự động Binding để ta có thể dễ dàng kết nối
#ví dụ như:
# env.DB.prepare("SELECT * FROM users WHERE name = ?1").bind("Joe");
binding = "DB"
database_name = "my-comment-db"
database_id = "<D1_DATABASE_ID>""
migrations_dir = "migrations"
preview_database_id = "db" #id database được dùng ở local

#được dùng để deploy UI
[assets]
directory = "./public"
binding = "ASSETS"

Bạn sẽ thay thế <D1_DATABASE_ID> bằng ID thực tế của D1 Database bạn đã tạo trên Cloudflare.

Binding là một cơ chế cấp quyền cho Worker, cho phép nó truy cập và thao tác với các tài nguyên khác trên tài khoản Cloudflare của bạn, chẳng hạn như đọc và ghi file vào bucket R2. Khi bạn khai báo một binding, bạn không cần phải cung cấp các khóa bí mật hoặc token, mà chỉ cần sử dụng API được cung cấp bởi binding. Điều này giúp bảo mật thông tin nhạy cảm vì khóa bí mật không bao giờ được tiết lộ cho code của Worker.

Code Worker để thêm và lấy bình luận

Dưới đây là đoạn mã mẫu để tạo API cho tính năng bình luận. Worker này sẽ nhận bình luận mới từ người dùng và lưu trữ chúng vào D1 Database.

Tạo Migrations

Để tạo mới một migration chúng ta sẽ dùng lệnh sau.

npx wrangler d1 migrations create my-comment-db init

Vì D1 có cơ chế hoạt động tương tự SQLite nên chúng ta sẽ cú pháp của SQLit để tạo bản "comment".

CREATE TABLE comments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    post_id INTEGER NOT NULL,
    username TEXT NOT NULL,
    comment TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Sau đó hãy chạy câu lệnh này để apply migration.

npx wrangler d1 migrations apply my-comment-db --local

Mở file index.ts

export default {
    async fetch(request, env, ctx): Promise<Response> {
        const url = new URL(request.url);

        if (request.method === 'POST' && url.pathname === '/comment') {
            const { comment, username }: { comment: string; username: string } = await request.json();

            // Add comment to the database
            await env.DB.prepare('INSERT INTO comments (post_id, username, comment) VALUES (?, ?, ?)').bind(1, username, comment).run();

            return new Response(JSON.stringify({ message: 'Comment added' }), { status: 200 });
        } else if (request.method === 'GET' && url.pathname === '/comments') {
            const { results } = await env.DB.prepare('SELECT * FROM comments').all();
            return new Response(JSON.stringify(results), { status: 200 });
        } else {
            return new Response('Not found', { status: 404 });
        }
    },
} satisfies ExportedHandler<Env>;

Tạo file public/index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    Hello World
  </body>
</html>

Sau khi hoàn tất chúng ta hãy chạy thử ứng dụng bằng lệnh sau:

npm run dev

Sau khi chạy thành công hãy truy cập vào đường dẫn http://127.0.0.1:8787http://127.0.0.1:8787/comments để xem thành quả.

Như vậy là chúng ta đã kết nối được với D1 và render được file index.html. Bây giờ chúng ta sẽ chuyển sang bước kết nối FE và BE lại với nhau.

Bước 3: Testing và Kết nối FE - BE

Bây giờ, bạn đã hoàn thành việc cấu hình tính năng bình luận trên nền tảng serverless. Bạn có thể kiểm thử bằng cách sử dụng Postman hoặc viết một giao diện front-end đơn giản để kết nối và hiển thị các bình luận.

Code giao diện đơn giản

Dưới đây là một ví dụ về cách sử dụng JavaScript để gửi bình luận từ front-end.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>NFC Reader</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 20px;
      }
      #commentForm {
        display: flex;
        flex-direction: column;
        max-width: 400px;
        margin: 0 auto;
      }
      #commentForm input,
      #commentForm textarea {
        margin-bottom: 10px;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
        font-size: 16px;
      }
      #commentForm button {
        padding: 10px;
        background-color: #007bff;
        color: white;
        border: none;
        border-radius: 4px;
        font-size: 16px;
        cursor: pointer;
      }
      #commentForm button:hover {
        background-color: #0056b3;
      }
      #commentsList {
        list-style-type: none;
        padding: 0;
        max-width: 400px;
        margin: 20px auto 0;
      }
      #commentsList li {
        background-color: #f9f9f9;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 4px;
        margin-bottom: 10px;
      }
    </style>
  </head>
  <body>
    <form id="commentForm">
      <input type="text" id="username" placeholder="Tên của bạn" required />
      <textarea id="comment" placeholder="Viết bình luận..." required></textarea>
      <button type="submit">Gửi bình luận</button>
    </form>
    <ul id="commentsList"></ul>

    <script>
      document.getElementById('commentForm').onsubmit = async (e) => {
        e.preventDefault()
        const username = document.getElementById('username').value
        const comment = document.getElementById('comment').value

        await fetch('/comment', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ username, comment }),
        })
        loadComments()

        document.getElementById('commentForm').reset()
      }

      async function loadComments() {
        const response = await fetch('/comments')
        const comments = await response.json()
        const commentsList = document.getElementById('commentsList')
        commentsList.innerHTML = ''
        comments.reverse().forEach((comment) => {
          const li = document.createElement('li')
          li.textContent = `${comment.username}: ${comment.comment}`
          commentsList.appendChild(li)
        })
      }

      loadComments()
    </script>
  </body>
</html>

Và đây là kết quả:

Screenshot 20241120 002547png

Bước 4: Deploy lên server

Sau khi đã test và mọi thứ đã hoạt động với nhau. Chúng ta sẽ tiến hành deploy lên server.

yarn deploy

Như vậy là bạn đã deploy xong ứng dụng của mình và giờ hãy truy cập vào đường dẫn được cung cấp và hưởng thụ thành quả thôi.

Kết luận

Với Cloudflare WorkerD1 Database, bạn đã có thể xây dựng một tính năng bình luận hosting miễn phí và dễ mở rộng mà không cần lo lắng về máy chủ. Giải pháp serverless này không chỉ giúp giảm chi phí mà còn tăng tốc độ tải, cải thiện trải nghiệm người dùng, đặc biệt phù hợp với các doanh nghiệp nhỏ và dự án cá nhân.