Miniflare 3 is a simulator for developing and testing
Cloudflare Workers, powered by
workerd
.
⚠️ Miniflare 3 is API-only, and does not expose a CLI. Use Wrangler withwrangler dev
to develop your Workers locally with Miniflare 3.
$ npm install miniflare --save-dev
import { Miniflare } from "miniflare";
// Create a new Miniflare instance, starting a workerd server
const mf = new Miniflare({
script: `addEventListener("fetch", (event) => {
event.respondWith(new Response("Hello Miniflare!"));
})`,
});
// Send a request to the workerd server, the host is ignored
const response = await mf.dispatchFetch("http://localhost:8787/");
console.log(await response.text()); // Hello Miniflare!
// Cleanup Miniflare, shutting down the workerd server
await mf.dispose();
T | Promise<T>
Represents a value that can be await
ed. Used in callback types to allow
Promise
s to be returned if necessary.
string | number | boolean | null | Record<string, Json> | Json[]
Represents a JSON-serialisable value.
"ESModule" | "CommonJS" | "Text" | "Data" | "CompiledWasm"
Represents how a module's contents should be interpreted.
"ESModule"
: interpret as ECMAScript module"CommonJS"
: interpret as CommonJS module"Text"
: interpret as UTF8-encoded data, expose in runtime withstring
-typeddefault
export"Data"
: interpret as arbitrary binary data, expose in runtime withArrayBuffer
-typeddefault
export"CompiledWasm"
: interpret as binary WebAssembly module data, expose in runtime withWebAssembly.Module
-typeddefault
export
Represents a manually defined module.
-
type: ModuleRuleType
How this module's contents should be interpreted.
-
path: string
Path of this module. The module's "name" will be obtained by converting this to a relative path. The original path will be used to read
contents
if it's omitted. -
contents?: string | Uint8Array
Contents override for this module. Binary data should be passed as
Uint8Array
s. If omitted, will be read frompath
.
Represents a rule for identifying the ModuleRuleType
of automatically located
modules.
-
type: ModuleRuleType
How to interpret modules that match the
include
patterns. -
include: string[]
Glob patterns to match located module paths against (e.g.
["**/*.txt"]
). -
fallthrough?: boolean
If
true
, ignore any further rules of thistype
. This is useful for disabling the built-inESModule
andCommonJS
rules that match*.mjs
and*.js
/*.cjs
files respectively.
boolean | string | undefined
Represents where data should be persisted, if anywhere.
- If this is
undefined
orfalse
, data will be stored in-memory and only persist betweenMiniflare#setOptions()
calls, not restarts nornew Miniflare
instances. - If this is
true
, data will be stored on the file-system, in the$PWD/.mf
directory. - If this looks like a URL, then:
- If the protocol is
memory:
, data will be stored in-memory as above. - If the protocol is
file:
, data will be stored on the file-system, in the specified directory (e.g.file:///path/to/directory
).
- If the protocol is
- Otherwise, if this is just a regular
string
, data will be stored on the file-system, using the value as the directory path.
NONE, ERROR, WARN, INFO, DEBUG, VERBOSE
Controls which messages Miniflare logs. All messages at or below the selected level will be logged.
-
prefix?: string
String to add before the level prefix when logging messages. Defaults to
mf
. -
suffix?: string
String to add after the level prefix when logging messages.
-
constructor(level?: LogLevel, opts?: LogOptions)
Creates a new logger that logs all messages at or below the specified level to the
console
. -
error(message: Error)
Logs a message at the
ERROR
level. If the constructed loglevel
is less thanERROR
,throw
s themessage
instead. -
warn(message: string)
Logs a message at the
WARN
level. -
info(message: string)
Logs a message at the
INFO
level. -
debug(message: string)
Logs a message at the
DEBUG
level. -
verbose(message: string)
Logs a message at the
VERBOSE
level.
-
constructor()
Creates a new logger that logs nothing to the
console
, and alwaysthrow
smessage
s logged at theERROR
level.
-
queueName: string
The name of the queue where messages will be sent by the producer.
-
deliveryDelay?: number
Default number of seconds to delay the delivery of messages to consumers. Value between
0
(no delay) and42300
(12 hours).
-
maxBatchSize?: number
Maximum number of messages allowed in each batch. Defaults to
5
. -
maxBatchTimeout?: number
Maximum number of seconds to wait for a full batch. If a message is sent, and this timeout elapses, a partial batch will be dispatched. Defaults to
1
. -
maxRetries?: number
Maximum number of times to retry dispatching a message, if handling it throws, or it is explicitly retried. Defaults to
2
. -
deadLetterQueue?: string
Name of another Queue to send a message on if it fails processing after
maxRetries
. If this isn't specified, failed messages will be discarded. -
retryDelay?: number
Number of seconds to delay the (re-)delivery of messages by default. Value between
0
(no delay) and42300
(12 hours).
Options for an individual Worker/"nanoservice". All bindings are accessible on
the global scope in service-worker format Workers, or via the 2nd env
parameter in module format Workers.
-
name: string
The name of the Workflow.
-
className: string
The name of the class exported from the Worker that implements the
WorkflowEntrypoint
. -
scriptName?
: stringThe name of the script that includes the
WorkflowEntrypoint
. This is optional because it defaults to the current script if not set.
-
name?: string
Unique name for this worker. Only required if multiple
workers
are specified. -
rootPath?: string
Path against which all other path options for this Worker are resolved relative to. This path is itself resolved relative to the
rootPath
fromSharedOptions
if multiple workers are specified. Defaults to the current working directory. -
script?: string
JavaScript code for this worker. If this is a service worker format Worker, it must not have any imports. If this is a modules format Worker, it must not have any npm imports, and
modules: true
must be set. If it does have imports,scriptPath
must also be set so Miniflare knows where to resolve them relative to. -
scriptPath?: string
Path of JavaScript entrypoint. If this is a service worker format Worker, it must not have any imports. If this is a modules format Worker, it must not have any npm imports, and
modules: true
must be set. -
modules?: boolean | ModuleDefinition[]
-
If
true
, Miniflare will treatscript
/scriptPath
as an ES Module and automatically locate transitive module dependencies according tomodulesRules
. Note that automatic location is not perfect: if the specifier to a dynamicimport()
orrequire()
is not a string literal, an exception will be thrown. -
If set to an array, modules can be defined manually. Transitive dependencies must also be defined. Note the first module must be the entrypoint and have type
"ESModule"
.
-
-
modulesRoot?: string
If
modules
is set totrue
or an array, modules' "name"s will be theirpath
s relative to this value. This ensures file paths in stack traces are correct.
-
modulesRules?: ModuleRule[]
Rules for identifying the
ModuleRuleType
of automatically located modules whenmodules: true
is set. Note the following default rules are always included at the end:[ { type: "ESModule", include: ["**/*.mjs"] }, { type: "CommonJS", include: ["**/*.js", "**/*.cjs"] }, ]
If
script
andscriptPath
are set, andmodules
is set to an array,modules
takes priority for a Worker's code, followed byscript
, thenscriptPath
.
-
compatibilityDate?: string
Compatibility date to use for this Worker. Defaults to a date far in the past.
-
compatibilityFlags?: string[]
Compatibility flags to use for this Worker.
-
bindings?: Record<string, Json>
Record mapping binding name to arbitrary JSON-serialisable values to inject as bindings into this Worker.
-
wasmBindings?: Record<string, string>
Record mapping binding name to paths containing binary WebAssembly module data to inject as
WebAssembly.Module
bindings into this Worker. -
textBlobBindings?: Record<string, string>
Record mapping binding name to paths containing UTF8-encoded data to inject as
string
bindings into this Worker. -
dataBlobBindings?: Record<string, string>
Record mapping binding name to paths containing arbitrary binary data to inject as
ArrayBuffer
bindings into this Worker. -
serviceBindings?: Record<string, string | typeof kCurrentWorker | { name: string | typeof kCurrentWorker, entrypoint?: string } | { network: Network } | { external: ExternalServer } | { disk: DiskDirectory } | (request: Request, instance: Miniflare) => Awaitable<Response>>
Record mapping binding name to service designators to inject as
{ fetch: typeof fetch }
service bindings into this Worker.- If the designator is a
string
, requests will be dispatched to the Worker with thatname
. - If the designator is
(await import("miniflare")).kCurrentWorker
, requests will be dispatched to the Worker defining the binding. - If the designator is an object of the form
{ name: ..., entrypoint: ... }
, requests will be dispatched to the entrypoint namedentrypoint
in the Worker namedname
. Theentrypoint
defaults todefault
, meaning{ name: "a" }
is the same as"a"
. Ifname
is(await import("miniflare")).kCurrentWorker
, requests will be dispatched to the Worker defining the binding. - If the designator is an object of the form
{ network: { ... } }
, wherenetwork
is aworkerd
Network
struct, requests will be dispatched according to thefetch
ed URL. - If the designator is an object of the form
{ external: { ... } }
whereexternal
is aworkerd
ExternalServer
struct, requests will be dispatched to the specified remote server. - If the designator is an object of the form
{ disk: { ... } }
wheredisk
is aworkerd
DiskDirectory
struct, requests will be dispatched to an HTTP service backed by an on-disk directory. - If the designator is a function, requests will be dispatched to your custom
handler. This allows you to access data and functions defined in Node.js
from your Worker. Note
instance
will be theMiniflare
instance dispatching the request.
- If the designator is a
-
wrappedBindings?: Record<string, string | { scriptName: string, entrypoint?: string, bindings?: Record<string, Json> }>
Record mapping binding name to designators to inject as wrapped bindings into this Worker. Wrapped bindings allow custom bindings to be written as JavaScript functions accepting an
env
parameter of "inner bindings" and returning the value to bind. Astring
designator is equivalent to{ scriptName: <string> }
.scriptName
's bindings will be used as "inner bindings". JSONbindings
in thedesignator
also become "inner bindings" and will override any ofscriptName
bindings with the same name. The Worker namedscriptName
...- Must define a single
ESModule
as its source, using{ modules: true, script: "..." }
,{ modules: true, scriptPath: "..." }
, or{ modules: [...] }
- Must provide the function to use for the wrapped binding as an
entrypoint
named export or a default export ifentrypoint
is omitted - Must not be the first/entrypoint worker
- Must not be bound to with service or Durable Object bindings
- Must not define
compatibilityDate
orcompatibilityFlags
- Must not define
outboundService
- Must not directly or indirectly have a wrapped binding to itself
- Must not be used as an argument to
Miniflare#getWorker()
Wrapped Bindings Example
import { Miniflare } from "miniflare"; const store = new Map<string, string>(); const mf = new Miniflare({ workers: [ { wrappedBindings: { MINI_KV: { scriptName: "mini-kv", // Use Worker named `mini-kv` for implementation bindings: { NAMESPACE: "ns" }, // Override `NAMESPACE` inner binding }, }, modules: true, script: `export default { async fetch(request, env, ctx) { // Example usage of wrapped binding await env.MINI_KV.set("key", "value"); return new Response(await env.MINI_KV.get("key")); } }`, }, { name: "mini-kv", serviceBindings: { // Function-valued service binding for accessing Node.js state async STORE(request) { const { pathname } = new URL(request.url); const key = pathname.substring(1); if (request.method === "GET") { const value = store.get(key); const status = value === undefined ? 404 : 200; return new Response(value ?? null, { status }); } else if (request.method === "PUT") { const value = await request.text(); store.set(key, value); return new Response(null, { status: 204 }); } else if (request.method === "DELETE") { store.delete(key); return new Response(null, { status: 204 }); } else { return new Response(null, { status: 405 }); } }, }, modules: true, script: ` // Implementation of binding class MiniKV { constructor(env) { this.STORE = env.STORE; this.baseURL = "http://x/" + (env.NAMESPACE ?? "") + ":"; } async get(key) { const res = await this.STORE.fetch(this.baseURL + key); return res.status === 404 ? null : await res.text(); } async set(key, body) { await this.STORE.fetch(this.baseURL + key, { method: "PUT", body }); } async delete(key) { await this.STORE.fetch(this.baseURL + key, { method: "DELETE" }); } } // env has the type { STORE: Fetcher, NAMESPACE?: string } export default function (env) { return new MiniKV(env); } `, }, ], });
⚠️ wrappedBindings
are only supported in modules format Workers. - Must define a single
-
outboundService?: string | { network: Network } | { external: ExternalServer } | { disk: DiskDirectory } | (request: Request) => Awaitable<Response>
Dispatch this Worker's global
fetch()
andconnect()
requests to the configured service. Service designators follow the same rules above forserviceBindings
. -
fetchMock?: import("undici").MockAgent
An
undici
MockAgent
to dispatch this Worker's globalfetch()
requests through.⚠️ outboundService
andfetchMock
are mutually exclusive options. At most one of them may be specified per Worker. -
routes?: string[]
Array of route patterns for this Worker. These follow the same routing rules as deployed Workers. If no routes match, Miniflare will fallback to the Worker defined first.
-
cache?: boolean
If
false
, default and named caches will be disabled. The Cache API will still be available, it just won't cache anything. -
cacheWarnUsage?: boolean
If
true
, the first use of the Cache API will log a warning stating that the Cache API is unsupported onworkers.dev
subdomains.
-
durableObjects?: Record<string, string | { className: string, scriptName?: string }>
Record mapping binding name to Durable Object class designators to inject as
DurableObjectNamespace
bindings into this Worker.- If the designator is a
string
, it should be the name of aclass
exported by this Worker. - If the designator is an object, and
scriptName
isundefined
,className
should be the name of aclass
exported by this Worker. - Otherwise,
className
should be the name of aclass
exported by the Worker with aname
ofscriptName
.
- If the designator is a
-
kvNamespaces?: Record<string, string> | string[]
Record mapping binding name to KV namespace IDs to inject as
KVNamespace
bindings into this Worker. Different Workers may bind to the same namespace ID with different binding names. If astring[]
of binding names is specified, the binding name and KV namespace ID are assumed to be the same. -
sitePath?: string
Path to serve Workers Sites files from. If set,
__STATIC_CONTENT
and__STATIC_CONTENT_MANIFEST
bindings will be injected into this Worker. In modules mode,__STATIC_CONTENT_MANIFEST
will also be exposed as a module with astring
-typeddefault
export, containing the JSON-stringified manifest. Note Workers Sites files are never cached in Miniflare. -
siteInclude?: string[]
If set, only files with paths matching these glob patterns will be served.
-
siteExclude?: string[]
If set, only files with paths not matching these glob patterns will be served.
assetsPath?: string
Path to serve Workers assets from.
-
assetsKVBindingName?: string
Name of the binding to the KV namespace that the assets are in. IfassetsPath
is set, this binding will be injected into this Worker. -
assetsManifestBindingName?: string
Name of the binding to anArrayBuffer
containing the binary-encoded assets manifest. IfassetsPath
is set, this binding will be injected into this Worker.
-
r2Buckets?: Record<string, string> | string[]
Record mapping binding name to R2 bucket names to inject as
R2Bucket
bindings into this Worker. Different Workers may bind to the same bucket name with different binding names. If astring[]
of binding names is specified, the binding name and bucket name are assumed to be the same.
-
d1Databases?: Record<string, string> | string[]
Record mapping binding name to D1 database IDs to inject as
D1Database
bindings into this Worker. Note binding names starting with__D1_BETA__
are injected asFetcher
bindings instead, and must be wrapped with a facade to provide the expectedD1Database
API. Different Workers may bind to the same database ID with different binding names. If astring[]
of binding names is specified, the binding name and database ID are assumed to be the same.
-
queueProducers?: Record<string, QueueProducerOptions> | string[]
Record mapping binding name to queue options to inject as
WorkerQueue
bindings into this Worker. Different Workers may bind to the same queue name with different binding names. If astring[]
of binding names is specified, the binding name and queue name (part of the queue options) are assumed to be the same. -
queueConsumers?: Record<string, QueueConsumerOptions> | string[]
Record mapping queue name to consumer options. Messages enqueued on the corresponding queues will be dispatched to this Worker. Note each queue can have at most one consumer. If a
string[]
of queue names is specified, default consumer options will be used.
-
directory?: string
Path to serve Workers static asset files from. -
binding?: string
Binding name to inject as aFetcher
binding to allow access to static assets from within the Worker. -
assetOptions?: { html_handling?: HTMLHandlingOptions, not_found_handling?: NotFoundHandlingOptions}
Configuration for file-based asset routing - see docs for options
-
pipelines?: Record<string, PipelineOptions> | string[]
Record mapping binding name to a Pipeline. Different workers may bind to the same Pipeline with different bindings names. If a
string[]
of pipeline names, the binding and Pipeline name are assumed to be the same.
workflows?: WorkflowOptions[]
Configuration for one or more Workflows in your project.
Not yet supported
If you need support for these locally, consider using the wrappedBindings
option to mock them out.
Not yet supported
If you need support for these locally, consider using the serviceBindings
option to mock them out.
Options shared between all Workers/"nanoservices".
-
rootPath?: string
Path against which all other path options for this instance are resolved relative to. Defaults to the current working directory.
-
host?: string
Hostname that the
workerd
server should listen on. Defaults to127.0.0.1
. -
port?: number
Port that the
workerd
server should listen on. Tries to default to8787
, but falls back to a random free port if this is in use. Note if a manually specified port is in use, Miniflare throws an error, rather than attempting to find a free port. -
https?: boolean
If
true
, start an HTTPS server using a pre-generated self-signed certificate forlocalhost
. Note this certificate is not valid for any other hostnames or IP addresses. If you need to access the HTTPS server from another device, you'll need to generate your own certificate and use the otherhttps*
options below.$ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out cert.pem
new Miniflare({ httpsKeyPath: "key.pem", httpsCertPath: "cert.pem", });
-
httpsKey?: string
When one of
httpsCert
orhttpCertPath
is also specified, starts an HTTPS server using the value of this option as the PEM encoded private key. -
httpsKeyPath?: string
When one of
httpsCert
orhttpCertPath
is also specified, starts an HTTPS server using the PEM encoded private key stored at this file path. -
httpsCert?: string
When one of
httpsKey
orhttpsKeyPath
is also specified, starts an HTTPS server using the value of this option as the PEM encoded certificate chain. -
httpsCertPath?: string
When one of
httpsKey
orhttpsKeyPath
is also specified, starts an HTTPS server using the PEM encoded certificate chain stored at this file path. -
inspectorPort?: number
Port that
workerd
should start a DevTools inspector server on. Visitchrome://inspect
in a Chromium-based browser to connect to this. This can be used to see detailedconsole.log
s, profile CPU usage, and will eventually allow step-through debugging. -
verbose?: boolean
Enable
workerd
's--verbose
flag for verbose logging. This can be used to see simplifiedconsole.log
s. -
log?: Log
Logger implementation for Miniflare's errors, warnings and informative messages.
-
upstream?: string
URL to use as the origin for incoming requests. If specified, all incoming
request.url
s will be rewritten to start with this string. This is especially useful when testing Workers that act as a proxy, and not as origins themselves. -
cf?: boolean | string | Record<string, any>
Controls the object returned from incoming
Request
'scf
property.- If set to a falsy value, an object with default placeholder values will be used
- If set to an object, that object will be used
- If set to
true
, a realcf
object will be fetched from a trusted Cloudflare endpoint and cached innode_modules/.mf
for 30 days - If set to a
string
, a realcf
object will be fetched and cached at the provided path for 30 days
-
liveReload?: boolean
If
true
, Miniflare will inject a script into HTML responses that automatically reloads the page in-browser whenever the Miniflare instance's options are updated.
-
cachePersist?: Persistence
Where to persist data cached in default or named caches. See docs for
Persistence
. -
durableObjectsPersist?: Persistence
Where to persist data stored in Durable Objects. See docs for
Persistence
. -
kvPersist?: Persistence
Where to persist data stored in KV namespaces. See docs for
Persistence
. -
r2Persist?: Persistence
Where to persist data stored in R2 buckets. See docs for
Persistence
. -
d1Persist?: Persistence
Where to persist data stored in D1 databases. See docs for
Persistence
. -
workflowsPersist?: Persistence
Where to persist data stored in Workflows. See docs for Persistence
.
Not yet supported
SharedOptions & (WorkerOptions | { workers: WorkerOptions[] })
Miniflare accepts either a single Worker configuration or multiple Worker
configurations in the workers
array. When specifying an array of Workers, the
first Worker is designated the entrypoint and will receive all incoming HTTP
requests. Some options are shared between all workers and should always be
defined at the top-level.
-
constructor(opts: MiniflareOptions)
Creates a Miniflare instance and starts a new
workerd
server. Note unlike Miniflare 2, Miniflare 3 always starts a HTTP server listening on the configuredhost
andport
: there are nocreateServer
/startServer
functions. -
setOptions(opts: MiniflareOptions)
Updates the configuration for this Miniflare instance and restarts the
workerd
server. Note unlike Miniflare 2, this does not merge the new configuration with the old configuration. Note that calling this function will invalidate any existing values returned by theMiniflare#get*()
methods, preventing them from being used. -
ready: Promise<URL>
Returns a
Promise
that resolves with ahttp
URL
to theworkerd
server once it has started and is able to accept requests. -
dispatchFetch(input: RequestInfo, init?: RequestInit): Promise<Response>
Sends a HTTP request to the
workerd
server, dispatching afetch
event in the entrypoint Worker. Returns aPromise
that resolves with the response. Note that this implicitly waits for theready
Promise
to resolve, there's no need to do that yourself first. Additionally, the host of the request's URL is always ignored and replaced with theworkerd
server's. -
getBindings<Env extends Record<string, unknown> = Record<string, unknown>>(workerName?: string): Promise<Env>
Returns a
Promise
that resolves with a record mapping binding names to bindings, for all bindings in the Worker with the specifiedworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
getWorker(workerName?: string): Promise<Fetcher>
Returns a
Promise
that resolves with aFetcher
pointing to the specifiedworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. Note thisFetcher
uses the experimentalservice_binding_extra_handlers
compatibility flag to exposescheduled()
andqueue()
methods for dispatchingscheduled
andqueue
events. -
getCaches(): Promise<CacheStorage>
Returns a
Promise
that resolves with theCacheStorage
instance of the entrypoint Worker. This means ifcache: false
is set on the entrypoint, calling methods on the resolved value won't do anything. -
getD1Database(bindingName: string, workerName?: string): Promise<D1Database>
Returns a
Promise
that resolves with theD1Database
instance corresponding to the specifiedbindingName
ofworkerName
. NotebindingName
must not begin with__D1_BETA__
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
getDurableObjectNamespace(bindingName: string, workerName?: string): Promise<DurableObjectNamespace>
Returns a
Promise
that resolves with theDurableObjectNamespace
instance corresponding to the specifiedbindingName
ofworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
getKVNamespace(bindingName: string, workerName?: string): Promise<KVNamespace>
Returns a
Promise
that resolves with theKVNamespace
instance corresponding to the specifiedbindingName
ofworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
getQueueProducer<Body>(bindingName: string, workerName?: string): Promise<Queue<Body>>
Returns a
Promise
that resolves with theQueue
producer instance corresponding to the specifiedbindingName
ofworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
getR2Bucket(bindingName: string, workerName?: string): Promise<R2Bucket>
Returns a
Promise
that resolves with theR2Bucket
producer instance corresponding to the specifiedbindingName
ofworkerName
. IfworkerName
is not specified, defaults to the entrypoint Worker. -
dispose(): Promise<void>
Cleans up the Miniflare instance, and shuts down the
workerd
server. Note that after this is called,Miniflare#setOptions()
andMiniflare#dispatchFetch()
cannot be called. Additionally, calling this function will invalidate any values returned by theMiniflare#get*()
methods, preventing them from being used. -
getCf(): Promise<Record<string, any>>
Returns the same object returned from incoming
Request
'scf
property. This object depends on thecf
property fromSharedOptions
.
You can override the workerd
binary being used by miniflare with a your own local build by setting the MINIFLARE_WORKERD_PATH
environment variable.
For example:
$ export MINIFLARE_WORKERD_PATH="<WORKERD_REPO_DIR>/bazel-bin/src/workerd/server/workerd"