@photonjs/cloudflare
@photonjs/cloudflare
v0.0.7Cloudflare Workers and Pages adapter for Photon applications.
npm install @photonjs/cloudflare
Exports
./vite
Vite plugin for Cloudflare integration.
import { cloudflare } from '@photonjs/cloudflare/vite'
./hono
Hono-specific Cloudflare utilities.
import { asFetch } from '@photonjs/cloudflare/hono'
./h3
H3-specific Cloudflare utilities.
import { asFetch } from '@photonjs/cloudflare/h3'
Functions
cloudflare(options?)
Vite plugin for Cloudflare Workers/Pages deployment.
function cloudflare(options?: CloudflareOptions): Plugin
Parameters:
options
- Optional Cloudflare-specific configuration
Returns: Vite plugin
Example:
// vite.config.ts
import { photon } from '@photonjs/core/vite'
import { cloudflare } from '@photonjs/cloudflare/vite'
export default {
plugins: [
photon({
server: './src/server.ts'
}),
cloudflare()
]
}
asFetch(app)
(Hono)
Convert a Hono app to a Cloudflare Workers fetch handler.
function asFetch(app: Hono): ExportedHandlerFetchHandler
Parameters:
app
- Hono application instance
Returns: Cloudflare Workers fetch handler
Example:
import { Hono } from 'hono'
import { asFetch } from '@photonjs/cloudflare/hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Cloudflare!'))
export default { fetch: asFetch(app) }
asFetch(app)
(H3)
Convert an H3 app to a Cloudflare Workers fetch handler.
function asFetch(app: App): ExportedHandlerFetchHandler
Parameters:
app
- H3 application instance
Returns: Cloudflare Workers fetch handler
Example:
import { createApp, defineEventHandler } from 'h3'
import { asFetch } from '@photonjs/cloudflare/h3'
const app = createApp()
app.use('/', defineEventHandler(() => 'Hello Cloudflare!'))
export default { fetch: asFetch(app) }
Configuration
CloudflareOptions
Configuration options for the Cloudflare adapter.
interface CloudflareOptions {
entry?: string
wrangler?: WranglerConfig
pages?: boolean
}
Entry Point
Specify custom entry point:
cloudflare({
entry: './cloudflare-entry.ts'
})
Wrangler Configuration
Integrate with Wrangler configuration:
cloudflare({
wrangler: {
configPath: './wrangler.toml',
environment: 'production'
}
})
Pages Mode
Enable Cloudflare Pages mode:
cloudflare({
pages: true
})
Virtual Modules
photon:cloudflare-entry
Virtual module that provides the Cloudflare entry point.
// cloudflare-entry.ts
import handler from 'photon:cloudflare-entry'
export default handler
This virtual module is automatically generated based on your Photon configuration and provides a ready-to-use Cloudflare Workers handler.
Environment Integration
Environment Variables
Access Cloudflare environment variables:
// In your handlers
app.get('/api/config', (c) => {
return c.json({
environment: c.env.ENVIRONMENT,
version: c.env.VERSION
})
})
KV Storage
Use Cloudflare KV for data storage:
app.get('/api/data/:key', async (c) => {
const key = c.req.param('key')
const value = await c.env.MY_KV.get(key)
if (!value) {
return c.notFound()
}
return c.json({ key, value })
})
app.put('/api/data/:key', async (c) => {
const key = c.req.param('key')
const value = await c.req.text()
await c.env.MY_KV.put(key, value)
return c.json({ success: true })
})
Durable Objects
Integrate with Durable Objects:
app.get('/api/counter', async (c) => {
const id = c.env.COUNTER.idFromName('global')
const stub = c.env.COUNTER.get(id)
const response = await stub.fetch(c.req.raw)
return response
})
WebSocket Support
Enable WebSocket support with crossws:
npm install crossws
import { upgradeWebSocket } from 'hono/cloudflare-workers'
app.get('/ws', upgradeWebSocket((c) => {
return {
onMessage: (event, ws) => {
ws.send(`Echo: ${event.data}`)
},
onClose: () => {
console.log('Connection closed')
}
}
}))
Advanced Usage
Custom Handler
Create a custom Cloudflare handler:
// cloudflare-entry.ts
import { Hono } from 'hono'
import { apply, serve } from '@photonjs/hono'
const app = new Hono()
// Your application logic
app.get('/', (c) => c.text('Hello!'))
// Apply Photon middleware
apply(app)
// Custom Cloudflare handler
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
// Custom logic before handling
console.log(`Request: ${request.method} ${request.url}`)
// Handle with Hono app
const response = await serve(app).fetch(request, env, ctx)
// Custom logic after handling
response.headers.set('X-Powered-By', 'Photon + Cloudflare')
return response
}
}
Edge Caching
Implement edge caching:
app.get('/api/cached', async (c) => {
const cache = caches.default
const cacheKey = new Request(c.req.url, c.req.raw)
let response = await cache.match(cacheKey)
if (!response) {
// Generate fresh response
response = new Response(JSON.stringify({
data: 'fresh',
timestamp: Date.now()
}), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=300'
}
})
// Cache the response
c.executionCtx.waitUntil(cache.put(cacheKey, response.clone()))
}
return response
})
Request Context
Access Cloudflare request context:
app.get('/api/info', (c) => {
return c.json({
// Cloudflare request properties
cf: c.req.raw.cf,
// Environment variables
environment: c.env.ENVIRONMENT,
// Request headers
country: c.req.header('cf-ipcountry'),
ip: c.req.header('cf-connecting-ip')
})
})
Deployment Integration
Wrangler Integration
The adapter integrates with Wrangler configuration:
# wrangler.toml
name = "my-photon-app"
main = "dist/cloudflare-entry.js"
compatibility_date = "2024-01-01"
[build]
command = "npm run build"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"
[vars]
ENVIRONMENT = "production"
Pages Functions
For Cloudflare Pages deployment:
// functions/_middleware.ts
import handler from '../dist/cloudflare-entry.js'
export const onRequest = handler
Error Handling
Global Error Handler
// In your server setup
app.onError((error, c) => {
console.error('Cloudflare error:', error)
return c.json({
error: 'Internal Server Error',
message: error.message,
timestamp: new Date().toISOString()
}, 500)
})
Graceful Degradation
app.get('/api/feature', async (c) => {
try {
// Try to use Cloudflare-specific feature
const result = await c.env.SOME_SERVICE.fetch(request)
return c.json(result)
} catch (error) {
// Fallback for other environments
console.warn('Cloudflare feature unavailable:', error)
return c.json({ message: 'Feature unavailable' }, 503)
}
})
Performance Optimization
CPU Time Optimization
// Optimize for Cloudflare's CPU time limits
app.use('*', async (c, next) => {
const start = Date.now()
const response = await next()
const duration = Date.now() - start
if (duration > 50) {
console.warn(`Slow request: ${duration}ms`)
}
return response
})
Memory Usage
// Optimize memory usage for Cloudflare limits
app.get('/api/large-data', async (c) => {
// Stream large responses instead of loading into memory
const stream = new ReadableStream({
start(controller) {
// Stream data in chunks
for (let i = 0; i < 1000; i++) {
controller.enqueue(`chunk ${i}\n`)
}
controller.close()
}
})
return new Response(stream, {
headers: { 'Content-Type': 'text/plain' }
})
})
Examples
Basic Setup
// vite.config.ts
import { photon } from '@photonjs/core/vite'
import { cloudflare } from '@photonjs/cloudflare/vite'
export default {
plugins: [
photon({
server: './src/server.ts'
}),
cloudflare()
]
}
Advanced Configuration
// vite.config.ts
export default {
plugins: [
photon({
server: './src/server.ts'
}),
cloudflare({
entry: './src/cloudflare-entry.ts',
pages: true,
wrangler: {
configPath: './wrangler.toml',
environment: 'production'
}
})
]
}