mirror of
https://github.com/kbenestad/mdcms.git
synced 2026-06-18 15:24:32 +00:00
213 lines
5.1 KiB
Markdown
213 lines
5.1 KiB
Markdown
---
|
|
title: Deploy to Cloudflare
|
|
sort: 110
|
|
section-id: deployment
|
|
keywords: Cloudflare, Pages, Workers, deployment, edge, CDN, Wrangler
|
|
description: Deploying a Velox application to Cloudflare Pages and Workers
|
|
language: en
|
|
---
|
|
|
|
# Deploy to Cloudflare
|
|
|
|
Velox runs natively on Cloudflare Workers. By combining Cloudflare Pages for static assets and Cloudflare Workers for server-side rendering, you get a globally distributed application with sub-millisecond cold starts.
|
|
|
|
## Architecture
|
|
|
|
Velox on Cloudflare uses:
|
|
- **Cloudflare Pages** — serves static assets from the CDN edge
|
|
- **Cloudflare Workers** — handles SSR requests at the edge
|
|
- **KV** — used for ISR page caching
|
|
- **D1** — SQLite-at-the-edge database (optional)
|
|
- **R2** — object storage for user uploads (optional)
|
|
|
|
## Setup
|
|
|
|
Install the Cloudflare adapter:
|
|
|
|
```bash
|
|
npm install @velox/cloudflare
|
|
npm install -D wrangler
|
|
```
|
|
|
|
Configure the adapter:
|
|
|
|
```typescript
|
|
// velox.config.ts
|
|
import { defineConfig } from 'velox';
|
|
import { cloudflare } from '@velox/cloudflare';
|
|
|
|
export default defineConfig({
|
|
adapter: cloudflare({
|
|
kvNamespace: 'VELOX_CACHE', // KV namespace for ISR cache
|
|
routes: {
|
|
exclude: ['/admin/*'], // serve these from Pages CDN only
|
|
},
|
|
}),
|
|
build: {
|
|
target: 'edge',
|
|
},
|
|
});
|
|
```
|
|
|
|
## Wrangler Configuration
|
|
|
|
Create `wrangler.toml`:
|
|
|
|
```toml
|
|
name = "my-velox-app"
|
|
compatibility_date = "2026-01-01"
|
|
compatibility_flags = ["nodejs_compat"]
|
|
pages_build_output_dir = ".velox/output"
|
|
|
|
[[kv_namespaces]]
|
|
binding = "VELOX_CACHE"
|
|
id = "your-kv-namespace-id"
|
|
|
|
[[d1_databases]]
|
|
binding = "DB"
|
|
database_name = "my-database"
|
|
database_id = "your-database-id"
|
|
|
|
[vars]
|
|
NODE_ENV = "production"
|
|
```
|
|
|
|
## Deployment Steps
|
|
|
|
### Option 1: Cloudflare Pages Dashboard
|
|
|
|
1. Go to [dash.cloudflare.com](https://dash.cloudflare.com) → **Pages** → **Create a project**
|
|
2. Connect your Git provider and select your repository
|
|
3. Set build settings:
|
|
- **Framework preset:** Velox
|
|
- **Build command:** `npm run build`
|
|
- **Build output directory:** `.velox/output`
|
|
4. Add environment variables
|
|
5. Click **Save and Deploy**
|
|
|
|
### Option 2: Wrangler CLI
|
|
|
|
```bash
|
|
# Log in
|
|
npx wrangler login
|
|
|
|
# Build
|
|
npm run build
|
|
|
|
# Deploy
|
|
npx wrangler pages deploy .velox/output --project-name my-velox-app
|
|
|
|
# Or deploy as a Worker
|
|
npx wrangler deploy
|
|
```
|
|
|
|
## Using Cloudflare D1 (SQLite at the Edge)
|
|
|
|
Cloudflare D1 is a serverless SQLite database that runs at the edge alongside your Workers.
|
|
|
|
### Create a Database
|
|
|
|
```bash
|
|
npx wrangler d1 create my-database
|
|
npx wrangler d1 execute my-database --file=./migrations/001_init.sql
|
|
```
|
|
|
|
### Query D1 in Velox
|
|
|
|
```typescript
|
|
// routes/api/posts+server.ts
|
|
import { defineHandler } from 'velox/server';
|
|
|
|
export const GET = defineHandler(async (req) => {
|
|
// env.DB is automatically injected by the Cloudflare adapter
|
|
const { DB } = process.env as any;
|
|
const { results } = await DB.prepare('SELECT * FROM posts WHERE published = 1').all();
|
|
return Response.json(results);
|
|
});
|
|
```
|
|
|
|
Or with Drizzle's D1 driver:
|
|
|
|
```typescript
|
|
import { drizzle } from 'drizzle-orm/d1';
|
|
import * as schema from '$lib/schema';
|
|
|
|
export function getDB(env: Env) {
|
|
return drizzle(env.DB, { schema });
|
|
}
|
|
```
|
|
|
|
## Using Cloudflare KV
|
|
|
|
For key-value storage (feature flags, cached responses):
|
|
|
|
```typescript
|
|
const value = await env.MY_KV.get('my-key');
|
|
await env.MY_KV.put('my-key', JSON.stringify(data), { expirationTtl: 3600 });
|
|
await env.MY_KV.delete('my-key');
|
|
```
|
|
|
|
## Using Cloudflare R2
|
|
|
|
For file uploads and object storage:
|
|
|
|
```typescript
|
|
// routes/api/upload+server.ts
|
|
import { defineHandler } from 'velox/server';
|
|
|
|
export const POST = defineHandler(async (req) => {
|
|
const formData = await req.formData();
|
|
const file = formData.get('file') as File;
|
|
|
|
const key = `uploads/${Date.now()}-${file.name}`;
|
|
await env.R2_BUCKET.put(key, file.stream(), {
|
|
httpMetadata: { contentType: file.type },
|
|
});
|
|
|
|
return Response.json({ url: `https://assets.example.com/${key}` });
|
|
});
|
|
```
|
|
|
|
## Custom Domains
|
|
|
|
1. Add your domain in Cloudflare's DNS settings (it should already be proxied through Cloudflare)
|
|
2. Go to Pages → Your project → **Custom domains**
|
|
3. Click **Set up a custom domain** and enter your domain
|
|
4. Cloudflare provisions SSL automatically
|
|
|
|
For Workers, add a route in `wrangler.toml`:
|
|
|
|
```toml
|
|
[[routes]]
|
|
pattern = "example.com/*"
|
|
zone_name = "example.com"
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
Set secrets securely:
|
|
|
|
```bash
|
|
npx wrangler secret put DATABASE_URL
|
|
npx wrangler secret put SESSION_SECRET
|
|
npx wrangler secret put JWT_SECRET
|
|
```
|
|
|
|
Non-secret variables go in `wrangler.toml` under `[vars]` or in the Pages dashboard.
|
|
|
|
## Performance Tips
|
|
|
|
- Use **Cache Rules** in the Cloudflare dashboard to cache SSR pages at the CDN layer
|
|
- Enable **Argo Smart Routing** for improved global routing
|
|
- Use **Tiered Cache** to reduce origin requests
|
|
- Set `Cache-Control: public, max-age=0, s-maxage=3600` on ISR pages to let Cloudflare cache them
|
|
|
|
## Limits
|
|
|
|
| Feature | Limit |
|
|
|---------|-------|
|
|
| Worker request timeout | 30s (CPU time) |
|
|
| Worker memory | 128 MB |
|
|
| KV value size | 25 MB |
|
|
| D1 database size | 2 GB |
|
|
| R2 object size | 5 GB |
|