Arek Nawo Hobbyist. Programmer. Dreamer. Freelancer. JavaScript and TypeScript lover. 👍 World-a-better-place maker. 🌐

Ditch the Wrangler CLI for Miniflare

4 min read 1191

Ditch the Wrangler CLI for Miniflare

Cloudflare Workers have been steadily growing in popularity — and for a good reason. They’re currently one of the top Function as a Service (FaaS) offerings, utilizing V8 isolates for 0ms cold starts and Cloudflare’s edge infrastructure for low latency. Overall, Workers provide excellent performance and vast scalability at an affordable price.

Problematic development experience

With that said, arguably the only aspect of Workers left to consider is the development experience. Even though Cloudflare provides high-quality development resources such as the Wrangler CLI, the Workers Dashboard, and detailed documentation, it can still be hard to develop for Workers’ unique environment. As V8 isolates are somewhere in between Node.js and standard browsers, they require custom solutions and APIs for things like storage or WebSocket access.

Usually, you’d use Wrangler CLI and, more specifically, the wrangler dev command to connect with Cloudflare’s servers and remotely develop for the Workers platform. This not only requires a good internet connection, but also limits your feature set to what your current Cloudflare plan allows. Not to mention polluting the production environment (e.g., with key-value (KV) storage) or having limited options for automated testing and CI/CD integration. That’s a sub-optimal development experience.

Thankfully, with a new tool called Miniflare, all of these issues go away.

What is Miniflare?

Miniflare is an open source Cloudflare Workers simulator that’s implemented with TypeScript and Node.js and can run locally without needing an internet connection.

Now, Miniflare has only recently become an official part of the Cloudflare Workers ecosystem. Because of that, it hasn’t yet been popularized or integrated into the ecosystem as much as Wrangler CLI has. However, it’s already fully-featured and has detailed documentation.

Miniflare simulates the entire Workers environment with runtime, KV storage, and supported Web Standards included. It also implements newer Workers features, such as Durable Objects and even early-access ones like WebSocket connection. Let’s see how it can make Workers development faster and easier!

Getting started

To get started with Miniflare, all you need is Node.js and npm:

mkdir worker
cd worker
npm init -y
npm install -D esbuild miniflare @cloudflare/workers-types

Additionally, use your bundler of choice if you intend on using modules or something like TypeScript. For this example, we’ll use esbuild — an extremely fast JS/TS bundler — and the @cloudflare/workers-types package to get the best TypeScript development experience possible.

Turning to config files, first set up your package.json file by adding the main field and some scripts.

  "main": "./dist/index.js",
  "scripts": {
    "build": "esbuild --bundle --sourcemap --outdir=dist ./src/index.ts",
    "dev": "miniflare --watch --debug"

Next, move over to wrangler.toml.

name = "esbuild-worker"
type = "javascript"
account_id = ""
workers_dev = true
route = ""
zone_id = ""
kv_namespaces = [
  { binding = "COUNTER_NAMESPACE", id = "", preview_id = "" },

command = "npm run build"
format = "service-worker"

If you’ve used the Wrangler CLI before, you’ll feel right at home. Miniflare accepts and respects the Wrangler CLI’s configuration keys, with an additional \[miniflare\] section for Miniflare-specific options.

Lastly, to make TypeScript work properly, create a tsconfig.json file referencing the Cloudflare Workers types.

  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "lib": ["ES2020"],
    "types": ["@cloudflare/workers-types"]

Creating Cloudflare Workers

With Miniflare set up, you can now start working on your new Worker — just like that! Create a src/index.ts file as your entry point, and use the addEventListener() function to listen for incoming requests.

addEventListener("fetch", (event) => {
  event.respondWith(new Response("test"));

The workflow and code are the same as when using Wrangler CLI.

To test your Worker, use the npm run dev command to start Miniflare’s development environment. Open the local URL provided by the CLI (port 8787 by default), and you should see the Worker’s output.

Miniflare can automatically rebuild your Worker after every file change and also display helpful debugging information. For that to work, you should use the \--watch and \--debug flags respectively.

Using Cloudflare Workers features

Like I’ve said, Miniflare simulates the entire Workers environment, including all of its dedicated features, like KV. Let’s see how it works in practice.

First, create a separate src/bindings.d.ts file. You can use it to declare globals specific to your Workers like KV namespaces or env variables. In this case, that’s a single KV namespace.

export {};

declare global {
  const COUNTER_NAMESPACE: KVNamespace;

Next, in your main file, create a function that will handle the request and interact with the KV storage.

const handleRequest = async (request: Request) => {
  const url = new URL(request.url);
  const currentValue = await COUNTER_NAMESPACE.get(url.pathname);
  const newValue = (parseInt(currentValue || "0") + 1).toString();

  await COUNTER_NAMESPACE.put(url.pathname, newValue);

  return new Response(newValue);

addEventListener("fetch", (event) => {

Now, you should see the counter increasing on each page refresh, meaning the KV storage works.

The counter increases, so the KV works

Using the Miniflare API

So, with local development, detailed debugging information, fast reloads, and access to all of Workers features, Miniflare is already a big win. With that said, probably its biggest advantage — yes, one we haven’t talked about yet — is its API.

With the Miniflare API, you can automate the entire process of building, running, and testing your Workers. You can also control things like KV storage or Durable Objects outside the Worker, leading to a whole new set of possibilities for Worker testing.

To play with the Miniflare API, create a new start.js file in your root directory. Inside the file, require() Miniflare and use its API to make requests to the Worker and access KV storage.

const { Miniflare } = require("miniflare");
const mf = new Miniflare();
const makeRequest = async () => {
  const res = await mf.dispatchFetch("http://localhost:8787/");

  return res.text();
const testNamespace = async () => {
  const counterNamespace = await mf.getKVNamespace("COUNTER_NAMESPACE");
  const count = await counterNamespace.get("/");

  console.log("KV:", count);

  return count;
const testRequests = async (times) => {
  for (let i = 0; i < times; i++) {
    console.log("Response:", await makeRequest());
const test = async () => {
  await testRequests(3);
  await testNamespace();


A dedicated Miniflare instance handles building and loading the Worker, while simultaneously providing access to the necessary APIs.

More great articles from LogRocket:

The above functions serve as an example of how you can test your Worker in a real-world scenario. testNamespace() retrieves a specific value from the KV storage’s COUNTER\_NAMESPACE, while the testRequests() function sends three requests to the Worker, making it write to KV, and logs the results.

Running the above snippet should output the following results:

Response 1
Response 2
Response 3
KV: 3


As you can see, Miniflare is a very capable simulator and development tool. Thanks to its vast features and advantages, I can recommend it for all Worker development and testing purposes. It dramatically accelerates and simplifies the whole process while allowing for much more testing possibilities.

With that said, Wrangler CLI isn’t going anywhere, and it’s still the best tool for deploying and verifying your Workers in the production environment. Testing your Worker on actual Cloudflare servers with actual production-level environment is something Miniflare can’t do.

All in all, it looks like Cloudflare Workers have a bright future, and I can’t wait to see what comes next!

Get setup with LogRocket's modern error tracking in minutes:

  1. Visit to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    Add to your HTML:

    <script src=""></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
Arek Nawo Hobbyist. Programmer. Dreamer. Freelancer. JavaScript and TypeScript lover. 👍 World-a-better-place maker. 🌐

Leave a Reply