使用Cloudflare D1与Astro为博客添加评论功能



自从博客部署到Cloudflare后,我就一直在寻找一个合适的评论系统。自我建立博客网站一开始,我的博客使用的是Disqus,但是Disqus在国内访问速度很慢,而且有时候还会被墙,所以我就放弃了。

后来了解了Valine,一直想要尝试一下,但因为太懒了没有尝试。

直到最近,我了解到了Cloudflare D1,以及Astro的Drizzle ORM,所以我就想要尝试一下,为我的博客添加评论功能。

技术栈

  • Cloudflare D1
  • Astro
  • Drizzle ORM
  • Bun

实现步骤

创建数据库以及表

在项目中可以通过wrangler命令行工具创建数据库以及表。

bash
1
bunx wrangler d1 create wonderland
1
bunx wrangler d1 create wonderland
bash
1
bunx wrangler d1 create wonderland
1
bunx wrangler d1 create wonderland

然后我在项目中放置了migrations/0001_init.sqlmigrations/0001_init.sql数据库迁移脚本。

sql
1
DROP TABLE IF EXISTS comments;
2
CREATE TABLE
3
    IF NOT EXISTS comments (
4
        id INTEGER PRIMARY KEY AUTOINCREMENT,
5
        post_slug TEXT NOT NULL, -- 文章唯一标识/slug
6
        author_name TEXT NOT NULL,
7
        author_email TEXT NOT NULL,
8
        author_url TEXT NOT NULL,
9
        content TEXT NOT NULL,
10
        created_at INTEGER NOT NULL DEFAULT (unixepoch ()),
11
        parent_id INTEGER,
12
        ip_hash TEXT
13
    );
14
    
15
CREATE INDEX IF NOT EXISTS idx_comments_post_created ON comments (post_slug, created_at DESC);
16

17
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
18
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
1
DROP TABLE IF EXISTS comments;
2
CREATE TABLE
3
    IF NOT EXISTS comments (
4
        id INTEGER PRIMARY KEY AUTOINCREMENT,
5
        post_slug TEXT NOT NULL, -- 文章唯一标识/slug
6
        author_name TEXT NOT NULL,
7
        author_email TEXT NOT NULL,
8
        author_url TEXT NOT NULL,
9
        content TEXT NOT NULL,
10
        created_at INTEGER NOT NULL DEFAULT (unixepoch ()),
11
        parent_id INTEGER,
12
        ip_hash TEXT
13
    );
14
    
15
CREATE INDEX IF NOT EXISTS idx_comments_post_created ON comments (post_slug, created_at DESC);
16

17
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
18
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
sql
1
DROP TABLE IF EXISTS comments;
2
CREATE TABLE
3
    IF NOT EXISTS comments (
4
        id INTEGER PRIMARY KEY AUTOINCREMENT,
5
        post_slug TEXT NOT NULL, -- 文章唯一标识/slug
6
        author_name TEXT NOT NULL,
7
        author_email TEXT NOT NULL,
8
        author_url TEXT NOT NULL,
9
        content TEXT NOT NULL,
10
        created_at INTEGER NOT NULL DEFAULT (unixepoch ()),
11
        parent_id INTEGER,
12
        ip_hash TEXT
13
    );
14
    
15
CREATE INDEX IF NOT EXISTS idx_comments_post_created ON comments (post_slug, created_at DESC);
16

17
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
18
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
1
DROP TABLE IF EXISTS comments;
2
CREATE TABLE
3
    IF NOT EXISTS comments (
4
        id INTEGER PRIMARY KEY AUTOINCREMENT,
5
        post_slug TEXT NOT NULL, -- 文章唯一标识/slug
6
        author_name TEXT NOT NULL,
7
        author_email TEXT NOT NULL,
8
        author_url TEXT NOT NULL,
9
        content TEXT NOT NULL,
10
        created_at INTEGER NOT NULL DEFAULT (unixepoch ()),
11
        parent_id INTEGER,
12
        ip_hash TEXT
13
    );
14
    
15
CREATE INDEX IF NOT EXISTS idx_comments_post_created ON comments (post_slug, created_at DESC);
16

17
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');
18
INSERT INTO comments (post_slug, author_name, author_email, author_url, content) VALUES ('test-slug', 'John Doe', 'john.doe@example.com', 'https://example.com', 'This is a test comment');

然后通过wrangler d1 executewrangler d1 execute命令执行数据库迁移脚本。

bash
1
bunx wrangler d1 execute wonderland --local --file=./migrations/0001_init.sql
1
bunx wrangler d1 execute wonderland --local --file=./migrations/0001_init.sql
bash
1
bunx wrangler d1 execute wonderland --local --file=./migrations/0001_init.sql
1
bunx wrangler d1 execute wonderland --local --file=./migrations/0001_init.sql

D1是一个非常神奇的数据库,它的命令可以分 本地远程 执行,只需要在命令中添加--local/--remote--local/--remote参数即可,这大大方便了开发和调试,意味着你本地可以随便折腾,不用担心对生产环境造成影响。