cloudflare部署D1 最近做点小工具,需要后端,但是不想买服务器了,就想着用Cloudflare的D1来部署,顺便学习一下。
Cloudflare D1 是 Cloudflare 提供的免费 SQLite 数据库服务,配合 Workers 可以快速构建无服务器后端应用。本文将介绍如何从零开始使用 Workers + D1 创建一个简单的 API 服务。
前置准备
注册 Cloudflare 账号
安装 Node.js
安装 Wrangler CLI:
登录 Cloudflare:
创建项目 1. 初始化 Workers 项目
按照提示选择:
What would you like to start with? → “Hello World” Worker
Do you want to deploy? → No
2. 创建 D1 数据库 1 wrangler d1 create my-database
复制返回的 database_id,然后更新 wrangler.toml 文件:
1 2 3 4 5 6 7 8 name = "my-d1-app" main = "src/index.js" compatibility_date = "2024-01-01" [[d1_databases]] binding = "DB" database_name = "my-database" database_id = "你的database_id"
设计数据库 创建一个简单的用户表作为示例:
migrations/0001_init.sql 内容:
1 2 3 4 5 6 CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL , email TEXT UNIQUE NOT NULL , created_at DATETIME DEFAULT CURRENT_TIMESTAMP );
执行迁移:
1 wrangler d1 execute my-database --local --file=./migrations/0001_init.sql
编写 Workers 代码 基础 API 结构 src/index.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 export default { async fetch (request, env, ctx ) { const url = new URL (request.url ); const path = url.pathname ; const method = request.method ; if (method === 'OPTIONS' ) { return new Response (null , { status : 204 , headers : { 'Access-Control-Allow-Origin' : '*' , 'Access-Control-Allow-Methods' : 'GET, POST, PUT, DELETE' , 'Access-Control-Allow-Headers' : 'Content-Type' , }, }); } if (path === '/api/users' && method === 'GET' ) { return getUsers (env.DB ); } else if (path === '/api/users' && method === 'POST' ) { return createUser (request, env.DB ); } else if (path.startsWith ('/api/users/' ) && method === 'GET' ) { const id = path.split ('/' ).pop (); return getUserById (id, env.DB ); } else if (path.startsWith ('/api/users/' ) && method === 'DELETE' ) { const id = path.split ('/' ).pop (); return deleteUser (id, env.DB ); } return new Response ('Not Found' , { status : 404 }); }, }; async function getUsers (db ) { try { const { results } = await db.prepare ('SELECT * FROM users ORDER BY created_at DESC' ).all (); return jsonResponse (results); } catch (error) { return jsonResponse ({ error : error.message }, 500 ); } } async function getUserById (id, db ) { try { const { results } = await db.prepare ('SELECT * FROM users WHERE id = ?' ).bind (id).all (); if (results.length === 0 ) { return jsonResponse ({ error : 'User not found' }, 404 ); } return jsonResponse (results[0 ]); } catch (error) { return jsonResponse ({ error : error.message }, 500 ); } } async function createUser (request, db ) { try { const { name, email } = await request.json (); if (!name || !email) { return jsonResponse ({ error : 'Name and email are required' }, 400 ); } const result = await db.prepare ('INSERT INTO users (name, email) VALUES (?, ?)' ) .bind (name, email) .run (); const { results } = await db.prepare ('SELECT * FROM users WHERE id = ?' ) .bind (result.meta .last_row_id ) .all (); return jsonResponse (results[0 ], 201 ); } catch (error) { if (error.message .includes ('UNIQUE' )) { return jsonResponse ({ error : 'Email already exists' }, 409 ); } return jsonResponse ({ error : error.message }, 500 ); } } async function deleteUser (id, db ) { try { const result = await db.prepare ('DELETE FROM users WHERE id = ?' ) .bind (id) .run (); if (result.meta .changes === 0 ) { return jsonResponse ({ error : 'User not found' }, 404 ); } return jsonResponse ({ message : 'User deleted successfully' }); } catch (error) { return jsonResponse ({ error : error.message }, 500 ); } } function jsonResponse (data, status = 200 ) { return new Response (JSON .stringify (data), { status, headers : { 'Content-Type' : 'application/json' , 'Access-Control-Allow-Origin' : '*' , }, }); }
本地开发 启动本地开发服务器:
服务将在 http://localhost:8787 运行。
测试 API 1 2 3 4 5 6 7 8 9 10 11 12 13 curl -X POST http://localhost:8787/api/users \ -H "Content-Type: application/json" \ -d '{"name":"张三","email":"zhangsan@example.com"}' curl http://localhost:8787/api/users curl http://localhost:8787/api/users/1 curl -X DELETE http://localhost:8787/api/users/1
部署到生产环境 1. 执行生产环境迁移 1 wrangler d1 execute my-database --remote --file=./migrations/0001_init.sql
2. 部署 Workers
部署成功后,你会获得一个 Workers URL,如 https://my-d1-app.你的账户名.workers.dev
进阶功能 添加分页功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 async function getUsers (db ) { const { searchParams } = new URL (request.url ); const page = parseInt (searchParams.get ('page' )) || 1 ; const limit = parseInt (searchParams.get ('limit' )) || 10 ; const offset = (page - 1 ) * limit; const { results } = await db.prepare ( 'SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?' ).bind (limit, offset).all (); const { count } = await db.prepare ('SELECT COUNT(*) as count FROM users' ).first (); return jsonResponse ({ data : results, pagination : { page, limit, total : count, totalPages : Math .ceil (count / limit), }, }); }
添加搜索功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 async function searchUsers (request, db ) { const { searchParams } = new URL (request.url ); const query = searchParams.get ('q' ); if (!query) { return jsonResponse ({ error : 'Search query is required' }, 400 ); } const { results } = await db.prepare ( 'SELECT * FROM users WHERE name LIKE ? OR email LIKE ?' ).bind (`%${query} %` , `%${query} %` ).all (); return jsonResponse (results); }
注意事项
免费额度 :D1 免费版每天有 5,000,000 次读取操作和 100,000 次写入操作
本地与远程 :使用 --local 参数在本地开发,使用 --remote 参数在生产环境操作
数据库备份 :定期导出数据备份:1 wrangler d1 export my-database --remote --output=backup.sql
安全性 :生产环境记得添加认证和输入验证
总结 Cloudflare Workers + D1 提供了一个简单、免费且强大的后端解决方案。通过本文的示例,你可以快速构建一个 RESTful API 服务。这种架构特别适合小型项目、个人博客后端或 API 原型开发。
参考资源