|
1 | | -# 🔥 Miniflare (WIP) |
| 1 | +# 🔥 Miniflare |
2 | 2 |
|
3 | | -Fun, fully-local Cloudflare Workers simulator for developing and testing Workers |
| 3 | +Fun, full-featured, fully-local simulator for developing and testing Cloudflare |
| 4 | +Workers |
| 5 | + |
| 6 | +**See <https://miniflare.dev> for many more details.** |
4 | 7 |
|
5 | 8 | ## Features |
6 | 9 |
|
| 10 | +- 📨 Fetch Events (with HTTP server and manual triggering) |
| 11 | +- ⏰ Scheduled Events (with manual and cron triggering) |
| 12 | +- 🔑 Variables and Secrets with `.env` Files |
| 13 | +- 📚 Modules Support |
7 | 14 | - 📦 KV (with optional persistence) |
8 | 15 | - ✨ Cache (with optional persistence) |
| 16 | +- 📌 Durable Objects (with optional persistence) |
9 | 17 | - 🌐 Workers Sites |
10 | | -- 📨 Fetch Events (with HTTP server and manual triggering) |
11 | | -- ⏰ Scheduled Events (with manual and cron triggering) |
12 | | -- 🔑 `.env` File Support (for secrets) |
| 18 | +- ✉️ WebSockets |
| 19 | +- 🛠 Custom & Wrangler Builds Support |
| 20 | +- ⚙️ WebAssembly Support |
13 | 21 | - 🗺 Source Map Support |
| 22 | +- 🕸 Web Standards: Base64, Timers, Fetch, Encoding, URL, Streams, Crypto |
| 23 | +- 📄 HTMLRewriter |
14 | 24 | - 👀 Automatic Reload on File Changes |
15 | 25 | - 💪 Written in TypeScript |
16 | 26 |
|
17 | | -## Coming Soon |
| 27 | +## Install |
18 | 28 |
|
19 | | -- 📌 Durable Objects |
20 | | -- ✉️ WebSockets |
21 | | -- 📄 HTMLRewriter |
22 | | -- 🛠 Custom Builds Support |
23 | | -- ⚙️ WebAssembly Support |
24 | | -- 🤹 Custom [Jest Environment](https://jestjs.io/docs/configuration#testenvironment-string) |
25 | | -- ✅ More Tests |
26 | | - |
27 | | -## CLI Usage |
| 29 | +Miniflare is installed using npm: |
28 | 30 |
|
| 31 | +```shell |
| 32 | +$ npm install -g miniflare # either globally.. |
| 33 | +$ npm install -D miniflare # ...or as a dev dependency |
29 | 34 | ``` |
30 | | -Usage: miniflare <script> [options] |
31 | 35 |
|
32 | | -Options: |
33 | | - -h, --help Show help [boolean] |
34 | | - -v, --version Show version number [boolean] |
35 | | - -p, --port HTTP server port (8787 by default) [number] |
36 | | - -d, --debug Log debug messages [boolean] |
37 | | - -c, --wrangler-config Path to wrangler.toml [string] |
38 | | - --wrangler-env Environment in wrangler.toml to use [string] |
39 | | - -w, --watch Watch files for changes [boolean] |
40 | | - -u, --upstream URL of upstream origin [string] |
41 | | - -t, --cron Cron pattern to trigger scheduled events with [array] |
42 | | - -k, --kv KV namespace to bind [array] |
43 | | - --kv-persist Path to persist KV data to (omit path for default) |
44 | | - --cache-persist Path to persist cached data to (omit path for default) |
45 | | - -s, --site Path to serve Workers Site files from [string] |
46 | | - --site-include Glob pattern of site files to serve [array] |
47 | | - --site-exclude Glob pattern of site files not to serve [array] |
48 | | - -e, --env Path to .env file [string] |
49 | | - -b, --binding Bind variable/secret (KEY=VALUE) [array] |
| 36 | +## Using the CLI |
| 37 | + |
| 38 | +```shell |
| 39 | +$ miniflare worker.js --watch --debug |
| 40 | +[mf:dbg] Options: |
| 41 | +[mf:dbg] - Scripts: worker.js |
| 42 | +[mf:dbg] Reloading worker.js... |
| 43 | +[mf:inf] Worker reloaded! |
| 44 | +[mf:dbg] Watching .env, worker.js, wrangler.toml... |
| 45 | +[mf:inf] Listening on :8787 |
| 46 | +[mf:inf] - http://127.0.0.1:8787 |
50 | 47 | ``` |
51 | 48 |
|
52 | | -`<script>` should be a path to a pre-bundled Worker. |
53 | | -If you're using Webpack for instance, set this to your output file. |
| 49 | +## Using the API |
54 | 50 |
|
55 | | -Use `--debug`/`-d` to see additional log messages including processed options and watched files. **(recommended)** |
| 51 | +```js |
| 52 | +import { Miniflare } from "miniflare"; |
56 | 53 |
|
57 | | -Use `--wrangler-config <toml_path>`/`-c <toml_path>` to load options for KV, cache, etc from a `wrangler.toml` file. **(recommended)** |
58 | | -You can also include an additional `[miniflare]` section for Miniflare specific configuration: |
59 | | - |
60 | | -```toml |
61 | | -[miniflare] |
62 | | -upstream = "https://mrbbot.dev" # --upstream |
63 | | -kv_persist = true # --kv-persist |
64 | | -cache_persist = true # --cache-persist |
65 | | -env_path = ".env" # --env |
66 | | -port = 8787 # --port |
| 54 | +const mf = new Miniflare({ |
| 55 | + script: ` |
| 56 | + addEventListener("fetch", (event) => { |
| 57 | + event.respondWith(new Response("Hello Miniflare!")); |
| 58 | + }); |
| 59 | + `, |
| 60 | +}); |
| 61 | +const res = await mf.dispatchFetch("http://localhost:8787/"); |
| 62 | +console.log(await res.text()); // Hello Miniflare! |
67 | 63 | ``` |
68 | 64 |
|
69 | | -KV and cache persistence can be enabled with the `--kv-persist` and `--cache-persist` flags respectively. |
70 | | -Including these on their own will store KV and Cache data in the `.mf` directory. |
71 | | -Optionally, you can specify a path (e.g. `--kv-persist ./data`) to use a different location. |
72 | | - |
73 | | -## Programmatic Usage |
74 | | - |
75 | | -```javascript |
76 | | -import vm from "vm"; |
77 | | -import { ConsoleLog, Miniflare, Request } from "miniflare"; |
78 | | - |
79 | | -// Loading script from file |
80 | | -const mf = new Miniflare("./path/to/script.js", { |
81 | | - // Some options omitted, see src/options/index.ts for the full list |
82 | | - sourceMap: true, |
83 | | - log: new ConsoleLog(), // Defaults to no-op logger |
84 | | - wranglerConfigPath: "wrangler.toml", |
85 | | - watch: true, |
86 | | - port: 8787, |
87 | | - upstream: "https://mrbbot.dev", |
88 | | - crons: ["0 * * * *"], |
89 | | - kvNamespaces: ["TEST_NAMESPACE"], |
90 | | - kvPersist: true, |
91 | | - cachePersist: "./data/", |
92 | | - sitePath: "./public/", |
93 | | - envPath: ".env", |
94 | | -}); |
| 65 | +## CLI Reference |
| 66 | + |
| 67 | +``` |
| 68 | +Usage: miniflare [script] [options] |
95 | 69 |
|
96 | | -// Loading script from string |
97 | | -const mf = new Miniflare( |
98 | | - new vm.Script(` |
99 | | - addEventListener("fetch", (event) => { |
100 | | - event.respondWith(handleRequest(event.request)); |
101 | | - event.waitUntil(Promise.resolve("Something")); |
102 | | - }); |
103 | | - |
104 | | - async function handleRequest(request) { |
105 | | - const value = await TEST_NAMESPACE.get("key"); |
106 | | - return new Response(\`Hello from Miniflare! key="\${value}"\`, { |
107 | | - headers: { "content-type": "text/plain" }, |
108 | | - }) |
109 | | - } |
110 | | - |
111 | | - addEventListener("scheduled", (event) => { |
112 | | - event.waitUntil(Promise.resolve("Something else")); |
113 | | - }); |
114 | | - `), |
115 | | - { |
116 | | - kvNamespaces: ["TEST_NAMESPACE"], |
117 | | - log: new ConsoleLog(), |
118 | | - } |
119 | | -); |
120 | | - |
121 | | -// Manipulate KV outside of worker (useful for testing) |
122 | | -const ns = await mf.getNamespace("TEST_NAMESPACE"); |
123 | | -await ns.put("key", "testing"); |
124 | | - |
125 | | -// Manipulate cache outside of worker |
126 | | -const cache = await mf.getCache(); |
127 | | -const cachedRes = await cache.match(new Request("http://localhost")); |
128 | | - |
129 | | -// Dispatch fetch events and get body |
130 | | -const res = await mf.dispatchFetch(new Request("http://localhost")); |
131 | | - |
132 | | -const body = await res.text(); |
133 | | -console.log(body); // Hello from Miniflare! key="testing" |
134 | | - |
135 | | -const waitUntil = await res.waitUntil(); |
136 | | -console.log(waitUntil[0]); // Something |
137 | | - |
138 | | -// Start HTTP server |
139 | | -mf.createServer().listen(3000); |
140 | | - |
141 | | -// Dispatch scheduled event at specific time |
142 | | -const waitUntil2 = await mf.dispatchScheduled(Date.now()); |
143 | | -console.log(waitUntil2[0]); // Something else |
| 70 | +Options: |
| 71 | + -h, --help Show help [boolean] |
| 72 | + -v, --version Show version number [boolean] |
| 73 | + -H, --host HTTP server host to listen on (all by default)[string] |
| 74 | + -p, --port HTTP server port (8787 by default) [number] |
| 75 | + -d, --debug Log debug messages [boolean] |
| 76 | + -c, --wrangler-config Path to wrangler.toml [string] |
| 77 | + --wrangler-env Environment in wrangler.toml to use [string] |
| 78 | + -m, --modules Enable modules [boolean] |
| 79 | + --modules-rule Modules import rule (TYPE=GLOB) [array] |
| 80 | + --build-command Command to build project [string] |
| 81 | + --build-base-path Working directory for build command [string] |
| 82 | + --build-watch-path Directory to watch for rebuilding on changes [string] |
| 83 | + -w, --watch Watch files for changes [boolean] |
| 84 | + -u, --upstream URL of upstream origin [string] |
| 85 | + -t, --cron Cron pattern to trigger scheduled events with [array] |
| 86 | + -k, --kv KV namespace to bind [array] |
| 87 | + --kv-persist Path to persist KV data to (omit path for default) |
| 88 | + --cache-persist Path to persist cached data to (omit path for default) |
| 89 | + -s, --site Path to serve Workers Site files from [string] |
| 90 | + --site-include Glob pattern of site files to serve [array] |
| 91 | + --site-exclude Glob pattern of site files not to serve [array] |
| 92 | + -o, --do Durable Object to bind (NAME=CLASS) [array] |
| 93 | + --do-persist Path to persist Durable Object data to (omit path for |
| 94 | + default) |
| 95 | + -e, --env Path to .env file [string] |
| 96 | + -b, --binding Bind variable/secret (KEY=VALUE) [array] |
| 97 | + --wasm WASM module to bind (NAME=PATH) [array] |
144 | 98 | ``` |
145 | 99 |
|
146 | 100 | ## Acknowledgements |
147 | 101 |
|
148 | | -Many thanks to [dollarshaveclub/cloudworker](https://github.com/dollarshaveclub/cloudworker) and [gja/cloudflare-worker-local](https://github.com/gja/cloudflare-worker-local) for inspiration. |
| 102 | +Many thanks to |
| 103 | +[dollarshaveclub/cloudworker](https://github.com/dollarshaveclub/cloudworker) |
| 104 | +and |
| 105 | +[gja/cloudflare-worker-local](https://github.com/gja/cloudflare-worker-local) |
| 106 | +for inspiration. |
0 commit comments