Edit this page

@photonjs/cloudflare

@photonjs/cloudflare

v0.0.7
Alpha

Cloudflare 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'
      }
    })
  ]
}