What is miniflare?
Miniflare is a simulator for Cloudflare Workers, allowing you to develop and test your Workers locally. It provides a local environment that mimics the Cloudflare Workers runtime, enabling you to test your code without deploying it to the cloud.
What are miniflare's main functionalities?
Local Development
Miniflare allows you to run and test your Cloudflare Workers locally. This example demonstrates how to create a simple worker that responds with 'Hello from Miniflare!' to any request.
const { Miniflare } = require('miniflare');
const mf = new Miniflare({
script: `addEventListener('fetch', event => {
event.respondWith(new Response('Hello from Miniflare!'));
})`
});
(async () => {
const res = await mf.dispatchFetch('http://localhost');
console.log(await res.text()); // Hello from Miniflare!
})();
KV Storage Simulation
Miniflare can simulate Cloudflare Workers KV storage, allowing you to test interactions with KV namespaces locally. This example shows how to store and retrieve a value from a KV namespace.
const { Miniflare } = require('miniflare');
const mf = new Miniflare({
script: `addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const value = await MY_KV_NAMESPACE.get('key');
return new Response(value);
}`,
kvNamespaces: ['MY_KV_NAMESPACE']
});
(async () => {
await mf.getKVNamespace('MY_KV_NAMESPACE').put('key', 'value');
const res = await mf.dispatchFetch('http://localhost');
console.log(await res.text()); // value
})();
Durable Objects Simulation
Miniflare supports simulating Durable Objects, which are used for stateful logic in Cloudflare Workers. This example demonstrates a simple counter Durable Object that increments its value with each request.
const { Miniflare } = require('miniflare');
const mf = new Miniflare({
script: `class Counter {
constructor(state, env) {
this.state = state;
this.env = env;
}
async fetch(request) {
let value = (await this.state.storage.get('value')) || 0;
value++;
await this.state.storage.put('value', value);
return new Response(value);
}
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const id = 'counter';
const stub = await COUNTER.get(id);
return stub.fetch(request);
}`,
durableObjects: { COUNTER: 'Counter' }
});
(async () => {
const res1 = await mf.dispatchFetch('http://localhost');
console.log(await res1.text()); // 1
const res2 = await mf.dispatchFetch('http://localhost');
console.log(await res2.text()); // 2
})();
Other packages similar to miniflare
wrangler
Wrangler is the official CLI tool for managing Cloudflare Workers. It allows you to develop, test, and deploy Workers, but unlike Miniflare, it does not provide a local simulation environment. Instead, it focuses on deployment and management tasks.
worktop
Worktop is a lightweight framework for building Cloudflare Workers. It provides utilities for routing, handling requests, and managing responses. While it simplifies the development of Workers, it does not offer the local simulation capabilities that Miniflare provides.
🔥 Miniflare
Fun, full-featured, fully-local simulator for developing and testing Cloudflare
Workers
See https://miniflare.dev for more detailed documentation.
Features
- 📨 Fetch Events (with HTTP server and manual triggering)
- ⏰ Scheduled Events (with manual and cron triggering)
- 🔑 Variables and Secrets with
.env
Files - 📚 Modules Support
- 📦 KV (with optional persistence)
- ✨ Cache (with optional persistence)
- 📌 Durable Objects (with optional persistence)
- 🌐 Workers Sites
- ✉️ WebSockets
- 🛠 Custom & Wrangler Builds Support
- ⚙️ WebAssembly Support
- 🗺 Source Map Support
- 🕸 Web Standards: Base64, Timers, Fetch, Encoding, URL, Streams, Crypto
- 📄 HTMLRewriter
- 👀 Automatic Reload on File Changes
- 💪 Written in TypeScript
Install
Miniflare is installed using npm:
$ npm install -g miniflare
$ npm install -D miniflare
Using the CLI
$ miniflare worker.js --watch --debug
[mf:dbg] Options:
[mf:dbg] - Scripts: worker.js
[mf:dbg] Reloading worker.js...
[mf:inf] Worker reloaded!
[mf:dbg] Watching .env, worker.js, wrangler.toml...
[mf:inf] Listening on :8787
[mf:inf] - http://127.0.0.1:8787
Using the API
import { Miniflare } from "miniflare";
const mf = new Miniflare({
script: `
addEventListener("fetch", (event) => {
event.respondWith(new Response("Hello Miniflare!"));
});
`,
});
const res = await mf.dispatchFetch("http://localhost:8787/");
console.log(await res.text());
CLI Reference
Usage: miniflare [script] [options]
Options:
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
-H, --host HTTP server host to listen on (all by default)[string]
-p, --port HTTP server port (8787 by default) [number]
-d, --debug Log debug messages [boolean]
-c, --wrangler-config Path to wrangler.toml [string]
--wrangler-env Environment in wrangler.toml to use [string]
-m, --modules Enable modules [boolean]
--modules-rule Modules import rule (TYPE=GLOB) [array]
--build-command Command to build project [string]
--build-base-path Working directory for build command [string]
--build-watch-path Directory to watch for rebuilding on changes [string]
-w, --watch Watch files for changes [boolean]
-u, --upstream URL of upstream origin [string]
-t, --cron Cron pattern to trigger scheduled events with [array]
-k, --kv KV namespace to bind [array]
--kv-persist Path to persist KV data to (omit path for default)
--cache-persist Path to persist cached data to (omit path for default)
-s, --site Path to serve Workers Site files from [string]
--site-include Glob pattern of site files to serve [array]
--site-exclude Glob pattern of site files not to serve [array]
-o, --do Durable Object to bind (NAME=CLASS) [array]
--do-persist Path to persist Durable Object data to (omit path for
default)
-e, --env Path to .env file [string]
-b, --binding Bind variable/secret (KEY=VALUE) [array]
--wasm WASM module to bind (NAME=PATH) [array]
Acknowledgements
Many thanks to
dollarshaveclub/cloudworker
and
gja/cloudflare-worker-local
for inspiration.
Durable Object's transactions are implemented using Optimistic Concurrency
Control (OCC) as described in
"On optimistic methods for concurrency control." ACM Transactions on Database Systems.
Thanks to Alistair O'Brien for helping me
understand this.