Astro กับ Hono: สร้าง Full-stack App บน Cloudflare Workers
#astro13 เม.ย. 2569
ทำไมต้อง Astro + Hono
Astro ดีสำหรับ frontend แต่ถ้าต้องการ API ที่ซับซ้อน Hono เป็นตัวเลือกที่ดีมาก ทั้งคู่ทำงานบน Cloudflare Workers ได้ดีเยี่ยม
ติดตั้ง
npx astro add cloudflare
npm install hono
ตั้งค่า Astro
// astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare()
});
สร้าง Hono API
// src/pages/api/[...path].ts
import { Hono } from 'hono';
import type { APIRoute } from 'astro';
const app = new Hono().basePath('/api');
app.get('/users', async (c) => {
const db = c.env.DB;
const users = await db.prepare('SELECT * FROM users').all();
return c.json(users.results);
});
app.post('/users', async (c) => {
const body = await c.req.json();
const db = c.env.DB;
await db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(body.name, body.email)
.run();
return c.json({ success: true }, 201);
});
export const ALL: APIRoute = ({ request, locals }) => {
return app.fetch(request, locals.runtime.env);
};
ใช้ API จาก Astro Page
---
// src/pages/users.astro
const response = await fetch('/api/users');
const users = await response.json();
---
<ul>
{users.map((user: any) => (
<li>{user.name} - {user.email}</li>
))}
</ul>
Middleware ร่วมกัน
app.use('*', async (c, next) => {
const token = c.req.header('Authorization');
if (!token) return c.json({ error: 'Unauthorized' }, 401);
await next();
});
D1 Database
// wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
app.get('/posts', async (c) => {
const { results } = await c.env.DB
.prepare('SELECT * FROM posts ORDER BY created_at DESC')
.all();
return c.json(results);
});
สรุป
Astro + Hono บน Cloudflare Workers เป็น stack ที่ทรงพลังมาก ได้ทั้ง static site performance และ full API capability ในราคาถูกมากครับ