💻 Using the CLI
The CLI is the easiest way to get started with Miniflare. It lets you start a local HTTP server that serves requests using your worker.
Installation
Miniflare is installed using npm
:
$ npm install -g miniflare # either globally...$ npm install -D miniflare # ...or as a dev dependency
You can also install and invoke the CLI using npx
:
$ npx miniflare
Usage
If worker.js
contains the following worker script:
worker.jsaddEventListener("fetch", (event) => { event.respondWith(new Response("Hello Miniflare!"));});
...running the following command will start a local HTTP server listening on
port 8787
that responds with Hello Miniflare!
to all requests:
$ miniflare worker.js[mf:inf] Worker reloaded! (97B)[mf:inf] Listening on :8787[mf:inf] - http://127.0.0.1:8787
Note that the uncompressed size of the worker, 97B
, is logged. Cloudflare
requires all workers are under 1MiB
once compressed. Miniflare will warn you
when your uncompressed size exceeds 1MiB
.
Watching and Debugging
Add --watch
/-w
and --debug
/-d
flags to reload the worker whenever
worker.js
changes and log debug information (including processed options)
respectively:
$ miniflare worker.js --watch --debug[mf:dbg] Options:[mf:dbg] - Script Path: worker.js[mf:dbg] Enabled Compatibility Flags: <none>[mf:dbg] Reloading worker.js...[mf:inf] Worker reloaded! (97B)[mf:dbg] Watching .env, package.json, worker.js, wrangler.toml...[mf:inf] Listening on :8787[mf:inf] - http://127.0.0.1:8787
Configuration Autoloading
Note that .env
, package.json
and wrangler.toml
files are also being
watched. These files are always loaded automatically and configure your worker's
environment in addition to the CLI flags. See the
Wrangler Configuration reference below for more
details, but as an example, with the following wrangler.toml
file and
worker.js
files:
wrangler.toml[vars]KEY = "value"
worker.jsaddEventListener("fetch", (event) => { event.respondWith(new Response(KEY));});
...the local HTTP server would respond with value
to all requests. The
Guide goes into more detail on configuring specific features. To
load a different wrangler.toml
file, use the --wrangler-config
/-c
flag:
$ miniflare worker.js --wrangler-config wrangler.other.toml
To change the directory these default files are resolved relative to, use the
--root
flag:
$ miniflare api/worker.js --root api# Miniflare will look for api/.env, api/package.json and api/wrangler.toml
Script Requirement
The only required option is the script to run. This can either be passed as a
command line argument as we've been doing so far, in a wrangler.toml
file or
in a package.json
file. The command line argument takes priority, then the
script in wrangler.toml
, then the main
or module
field in package.json
(depending on whether modules
support is enabled):
wrangler.toml[build.upload]dir = "" # Defaults to "dist"main = "./worker.js"
package.json{ "main": "worker.js", // "service-worker" format "module": "worker.mjs" // "modules" format}
Request#cf
Object
For a more accurate development experience, Miniflare automatically fetches the
cf
object for incoming requests (containing IP and location data) from a
trusted Cloudflare endpoint, caching it for 30 days. You can disable this
behaviour, falling back to a default cf
object, using the --no-cf-fetch
flag:
$ miniflare worker.js --no-cf-fetch
HTTPS Server
By default, Miniflare starts an HTTP server. To start an HTTPS server instead,
set the https
option. To use an automatically generated self-signed
certificate, use the --https
flag. This certificate is cached and will be
valid for 30 days. The certificate will be renewed if it expires in less than 2
days:
$ miniflare worker.js --https # Cache certificate in ./.mf/cert$ miniflare worker.js --https ./cert_cache # Cache in ./cert_cache instead
To use an existing certificate instead, use the --https-key
, --https-cert
,
--https-ca
and --https-pfx
flags to set the paths to it. If these are
encrypted, use the --https-passphrase
flag to set the passphrase:
$ miniflare worker.js --https-key ./key.pem --https-cert ./cert.pem
Opening the Browser
Add the --open
/-O
flag to automatically open your default browser to the
worker, once the HTTP server has started:
$ miniflare worker.js --open # Opens http://localhost:8787$ miniflare worker.js --open https://example.com # Opens https://example.com
REPL
Add the --repl
flag to start an interactive REPL session. This behaves exactly
like the Node.js REPL, except you have
access to Workers Runtime APIs instead. Any other Miniflare flag can be used
too, with .env
, package.json
and wrangler.toml
files automatically loaded.
Specifying a script is optional when --repl
is enabled, but may be required if
you're using Durable Objects. If you're using an ES module format worker,
bindings will be accessible via the env
global variable.
The REPL can be configured using environment variables similar to Node.js:
MINIFLARE_REPL_HISTORY
: path to save REPL history to. Setting this to an empty string disables persistent REPL history. Defaults to~/.mf_repl_history
.MINIFLARE_REPL_HISTORY_SIZE
: number of history lines to save if persistent REPL history is enabled. Defaults to1000
.MINIFLARE_REPL_MODE
: eithersloppy
orstrict
. Defaults tosloppy
allowing non-strict code to run.
$ miniflare --repl --kv TEST_NAMESPACE> await new HTMLRewriter().on("p", {... element(e) {..... e.setInnerContent("new");..... }... }).transform(new Response("<p>old</p>")).text()'<p>new</p>'> await env.TEST_NAMESPACE.put("key", "value")undefined> await env.TEST_NAMESPACE.get("key")'value'>
Update Checker
The CLI includes an automatic update checker that looks for new versions of
Miniflare once a day. As Cloudflare are always improving and tweaking workers,
you should aim to install these promptly for improved compatibility with the
real Workers environment. You can disable this with the --no-update-check
flag.
Reference
Flags
Usage: miniflare [script] [options]
Core Options: -h, --help Show help [boolean] -v, --version Show version number [boolean] -c, --wrangler-config Path to wrangler.toml [string] --wrangler-env Environment in wrangler.toml to use [string] --package Path to package.json [string] -m, --modules Enable modules [boolean] --modules-rule Modules import rule [array:TYPE=GLOB] --compat-date Opt into backwards-incompatible changes from [string] --compat-flag Control specific backwards-incompatible changes [array] --usage-model Usage model (bundled by default) [string] -u, --upstream URL of upstream origin [string] -w, --watch Watch files for changes [boolean] -d, --debug Enable debug logging [boolean] -V, --verbose Enable verbose logging [boolean] --(no-)update-check Enable update checker (enabled by default) [boolean] --repl Enable interactive REPL [boolean] --root Path to resolve files relative to [string] --mount Mount additional named workers [array:NAME=PATH[@ENV]] --name Name of service [string] --route Route to respond with this worker on [array] --global-async-io Allow async I/O outside handlers [boolean] --global-timers Allow setting timers outside handlers [boolean] --global-random Allow secure random generation outside [boolean] handlers --actual-time Always return correct time from Date methods [boolean] --inaccurate-cpu Log inaccurate CPU time measurements [boolean]
HTTP Options: -H, --host Host for HTTP(S) server to listen on [string] -p, --port Port for HTTP(S) server to listen on [number] -O, --open Automatically open browser to URL [boolean/string] --https Enable self-signed HTTPS (with [boolean/string] optional cert path) --https-key Path to PEM SSL key [string] --https-cert Path to PEM SSL cert chain [string] --https-ca Path to SSL trusted CA certs [string] --https-pfx Path to PFX/PKCS12 SSL key/cert chain [string] --https-passphrase Passphrase to decrypt SSL files [string] --(no-)cf-fetch Path for cached Request cf object from [boolean/string] Cloudflare --live-reload Reload HTML pages whenever worker is reloaded [boolean]
Scheduler Options: -t, --cron CRON expression for triggering scheduled events [array]
Build Options: -B, --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 [array]
KV Options: -k, --kv KV namespace to bind [array] --kv-persist Persist KV data (to optional path) [boolean/string]
R2 Options: -r, --r2 R2 bucket to bind [array] --r2-persist Persist R2 data (to optional path) [boolean/string]
Durable Objects Options: -o, --do Durable Object to bind [array:NAME=CLASS[@MOUNT]] --do-persist Persist Durable Object data (to [boolean/string] optional path) --(no-)do-alarms Enable Durable Object alarms (enabled by [boolean] default)
Cache Options: --(no-)cache Enable default/named caches (enabled by [boolean] default) --cache-persist Persist cached data (to optional path) [boolean/string]
Sites Options: -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]
Bindings Options: -e, --env Path to .env file [string] -b, --binding Binds variable/secret to environment [array:KEY=VALUE] --global Binds variable/secret to global scope [array:KEY=VALUE] --wasm WASM module to bind [array:NAME=PATH] --text-blob Text blob to bind [array:NAME=PATH] --data-blob Data blob to bind [array:NAME=PATH] -S, --service Mounted service to bind [array:NAME=MOUNT[@ENV]]
Wrangler Configuration
Miniflare uses the default Wrangler configuration keys for most of its features.
For Miniflare specific options, the keys are in the special [miniflare]
section.
wrangler.tomlname = "worker" # --name
compatibility_date = "2021-11-12" # --compat-datecompatibility_flags = [ # --compat-flag "formdata_parser_supports_files"]
kv_namespaces = [ # --kv { binding = "TEST_NAMESPACE", id = "", preview_id = "" }]
r2_buckets = [ # --r2 { binding = "BUCKET", bucket_name = "" }]
[durable_objects]bindings = [ # --do { name = "OBJECT", class_name = "Object" }]
[vars] # --bindingKEY = "value"
[site]bucket = "./public" # --siteinclude = ["upload_dir"] # --site-includeexclude = ["ignore_dir"] # --site-exclude
[triggers]crons = ["30 * * * *"] # --cron
[build]command = "npm run build" # --build-commandcwd = "build_cwd" # --build-base-pathwatch_dir = "build_watch_dir" # --build-watch-path[build.upload]format = "modules" # --modulesdir = "worker"main = "./index.mjs" # [script][[build.upload.rules]] # --modules-ruletype = "ESModule"globs = ["**/*.js"]
[wasm_modules] # --wasmMODULE = "module.wasm"[text_blobs] # --text-blobTEXT = "text.txt"[data_blobs] # --data-blobDATA = "data.bin"
[miniflare]host = "127.0.0.1" # --hostport = 1337 # --portupstream = "https://miniflare.dev" # --upstreamwatch = true # --watchlive_reload = true # --live-reloadenv_path = ".env.test" # --envkv_persist = true # --kv-persistr2_persist = true # --r2-persistcache_persist = "./cache" # --cache-persistcache = false # --no-cachedurable_objects_persist = true # --do-persistdurable_objects_alarms = false # --no-do-alarmsupdate_check = false # --no-update-checkcf_fetch = "./cf.json" # --cf-fetch ./cf.jsoncf_fetch = false # --no-cf-fetchhttps = true # --httpshttps = "./cert_cache" # --https ./cert_cacheactual_time = true # --actual-timeglobal_async_io = true # --global-async-ioglobal_timers = true # --global-timersglobal_random = true # --global-randomactual_time = true # --actual-timeinaccurate_cpu = true # --inaccurate-cpu[miniflare.https]key = "./key.pem" # --https-keycert = "./cert.pem" # --https-certca = "./ca.pem" # --https-capfx = "./pfx.pfx" # --https-pfxpassphrase = "pfx passphrase" # --https-passphrase[miniflare.globals] # --globalKEY = "value"[miniflare.mounts] # --mountapi = "./api"