Cloudflare Workers
@mionjs/platform-cloudflare provides a Web standard Request -> Response fetch handler with access to Worker bindings.
Installing the Adapter
npm install @mionjs/platform-cloudflare @mionjs/router
Creating the Handler
import {createCloudflareHandler} from '@mionjs/platform-cloudflare';
import './cloudflare-routes.ts';
export default createCloudflareHandler();
import {createMionRouter, Routes} from '@mionjs/router';
const mion = createMionRouter();
const routes = {
sayHello: mion.route((ctx, name: string): string => {
return `Hello ${name}!`;
}),
} satisfies Routes;
// the server entry only imports this file
export const myApi = mion.initRoutes(routes);
export type MyApi = typeof myApi;
Cloudflare Configuration
A minimal wrangler.toml for a mion Worker, where main points to the Vite bundle. Run wrangler deploy to publish.
name = "my-mion-api"
main = "dist/worker.js"
compatibility_date = "2024-01-01"
Handler Options
Pass options such as maxBodySize (128 KB by default) and maxBodySizeCap to createCloudflareHandler. maxBodySizeCap defaults to the 100 MB Cloudflare allows on the Free and Pro plans; override it on Business or Enterprise, which allow more. The handler's basePath strips a URL prefix before routing. Router options, including the router's own basePath, go in createMionRouter. Each route has its own body limit, and a streamed body is cancelled with a 413 the moment it passes it.
import {createCloudflareHandler} from '@mionjs/platform-cloudflare';
import './cloudflare-routes.ts';
export default createCloudflareHandler({
basePath: '/api',
maxBodySize: 512 * 1024,
});
env (your Worker bindings: KV, D1, R2, secrets, etc.) and ctx (the Worker ExecutionContext with waitUntil/passThroughOnException) on the call context's platform context. Use it to read Worker bindings in your route handlers.Vite Configuration
A minimal vite.config.ts for a Worker. The Worker entry needs no special setup beyond Creating the Handler.
new Function() or eval(), so a Worker build must set
runTypes: {emitMode: 'both'} on the mion Vite plugin.The default emitMode: 'code' ships each build-time compiled function as a source string that
new Function turns into a real function on first use, and mion.initRoutes fails on the first route
with "Code generation from strings disallowed for this context". 'both' also ships the live function,
so nothing is compiled at runtime or at cold start. The cost: roughly +30% raw bundle size, +15% gzipped.import {defineConfig} from 'vite';
import {resolve} from 'path';
import {mionVitePlugin} from '@mionjs/devtools/vite';
export default defineConfig({
plugins: [
mionVitePlugin({
tsConfig: resolve(__dirname, 'tsconfig.json'),
runTypes: {
// required on Workers: no `new Function` at runtime
emitMode: 'both',
},
}),
],
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: 'worker',
},
rollupOptions: {
// Workers do not support dynamic code splitting, so bundle everything into one file
output: {inlineDynamicImports: true},
},
},
});
Cloudflare Databases
Cloudflare's two SQLite databases, D1 and Durable Objects storage, both work with the SQLite table package. Declare the table once and pick the driver where you connect, see Cloudflare D1 and Durable Objects.