npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mock-service-plugin

v26.327.0

Published

Simulated backend interface service

Readme

mock-service-plugin

English | 中文

A powerful local Mock service plugin that supports Webpack, Vite, and other mainstream build tools — letting you develop and debug frontend pages even before the backend APIs are ready.

Table of Contents


What is Mocking?

In real-world development, frontend and backend teams often work in parallel. When the backend APIs aren't ready yet, the frontend has no data to work with and development stalls.

Mocking means running a fake backend service locally that returns dummy data according to the agreed API contract, so frontend development can proceed independently without relying on a real backend.

What mock-service-plugin does is: read your mock data files, automatically start a local HTTP server, and return the corresponding data when frontend requests come in.


Features

  • 🚀 Supports multiple build tools: Webpack 4/5, Vite, Vue CLI, Create React App
  • 🎯 Compatible with Vue, React, and other mainstream frameworks
  • 🔥 Feature-rich
    • RESTful API support (GET / POST / PUT / DELETE, etc.)
    • Dynamic route parameters (e.g. /api/users/:id)
    • Streaming responses (SSE / EventStream, simulates AI typewriter effect)
    • Multiple response formats (JSON / XML / CSV / Image / Plain text, etc.)
  • 💡 Minimal configuration, hot reload, built-in debug interface

Installation

# npm
npm install mock-service-plugin --save-dev

# yarn
yarn add mock-service-plugin --dev

# pnpm
pnpm add mock-service-plugin --save-dev

5-Minute Quick Start

The following uses a Vite + Vue project as an example to walk you through your first Mock API from scratch.

Step 1: Install the Plugin

npm install mock-service-plugin --save-dev

Step 2: Create the Mock Directory and File

Create a mocks folder in the project root and add a file mocks/user.json:

project-root/
├── mocks/
│   └── user.json   ← create this file
├── src/
├── vite.config.ts
└── package.json

Contents of mocks/user.json:

/**
 * @url /api/user/info
 * @method GET
 */
{
  "code": 200,
  "data": {
    "id": "@id",
    "name": "@cname",
    "email": "@email",
    "avatar": "@image('100x100')"
  },
  "message": "success"
}

The /** ... */ comment at the top is the route configuration, telling the plugin which API path and HTTP method this file corresponds to.
@cname, @email, etc. are MockJS random data placeholders — each request generates different random data. See MockJS Syntax Reference for full syntax.

Step 3: Start the Mock Service in Vite

Create vite-mock-plugin.ts in the project root:

// vite-mock-plugin.ts
import { startServer } from "mock-service-plugin";
import { createServer } from "net";
import { join } from "path";

// Check if a port is already in use
function isPortTaken(port: number): Promise<boolean> {
  return new Promise((resolve) => {
    const server = createServer();
    server.once("error", (err: { code: string }) => {
      resolve(err.code === "EADDRINUSE");
    });
    server.once("listening", () => {
      server.close();
      resolve(false);
    });
    server.listen(port);
  });
}

// Vite plugin: start Mock service in mock mode
export default function ViteMockServicePlugin(mode: string) {
  return {
    name: "ViteMockServicePlugin",
    buildStart() {
      (async () => {
        const port = 3008;
        if (await isPortTaken(port)) {
          console.log(`[Mock] Port ${port} is already in use, skipping start`);
          return;
        }
        if (mode === "mock") {
          startServer({
            mockDir: join(__dirname, "./mocks"), // path to mock folder
            port,                                // mock service port
          });
        }
      })();
    },
  };
}

Update vite.config.ts:

// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import ViteMockServicePlugin from "./vite-mock-plugin";

export default defineConfig(({ mode }) => ({
  plugins: [
    vue(),
    ViteMockServicePlugin(mode), // pass current mode
  ],
  server: {
    proxy: {
      // Proxy /api requests to the mock service
      "/api": {
        target: "http://localhost:3008",
        changeOrigin: true,
      },
    },
  },
}));

Add a mock start script to package.json:

{
  "scripts": {
    "dev": "vite --mode dev",
    "mock": "vite --mode mock"
  }
}

Step 4: Start and Test

npm run mock

After starting, open http://localhost:3008/api/user/info in your browser and you'll see randomly generated user data:

{
  "code": 200,
  "data": {
    "id": "660000198812040277",
    "name": "Han Lei",
    "email": "[email protected]",
    "avatar": "http://dummyimage.com/100x100"
  },
  "message": "success"
}

Congratulations! You've successfully set up your first Mock API. 🎉


Mock File Specification

File Structure

Each mock file consists of two parts:

file = top comment (route config) + response body
/**
 * @url /api/users        ← required: API path
 * @method GET            ← optional: HTTP method, defaults to GET
 */
{
  "code": 200,
  "data": []
}

Annotation Reference

| Annotation | Required | Description | Example | |------------|----------|-------------|---------| | @url | ✅ Yes | API path, supports dynamic parameters | @url /api/users/:id | | @method | Optional | HTTP method, defaults to GET | @method POST | | @content-type | Optional | Override the default Content-Type. Preferably use the file extension as reference — see Supported File Formats. | @content-type image/png |

Dynamic Route Parameters

Use :paramName to define dynamic path segments:

/**
 * @url /api/users/:id
 * @method GET
 */
{
  "id": "@id",
  "name": "@cname"
}

Both /api/users/123 and /api/users/456 will match this file.

Managing Multiple APIs in One Directory

It's recommended to organize files by business module:

mocks/
├── user.json        → /api/user/...
├── product.json     → /api/product/...
├── orders.csv       → /api/orders
├── banner.xml       → /api/banner
└── stream.sse       → /api/stream (streaming response)

The plugin recursively scans the entire mocks directory and automatically registers all routes found in every file.


MockJS Syntax Reference

MockJS is a data mocking library that generates random data using template syntax. The plugin bundles MockJS, so it can be used directly in .json mock files.

Random Value Placeholders

See Full Syntax Categories

| Syntax | Description | Example Output | |--------|-------------|----------------| | @id | Random ID number | "420000199206230937" | | @guid | Random GUID | "662C63B4-FD43-66F4-3328" | | @cname | Random Chinese name | "Wang Fang" | | @name | Random English name | "Charles Lopez" | | @email | Random email address | "[email protected]" | | @url | Random URL | "http://ljwih.io/lxqf" | | @ip | Random IP address | "52.249.14.3" | | @integer(min, max) | Random integer in range | @integer(1, 100)42 | | @float(min, max, dMin, dMax) | Random float | @float(1, 100, 2, 2)36.14 | | @boolean | Random boolean | true or false | | @date | Random date | "2021-07-30" | | @datetime | Random datetime | "2021-07-30 10:42:01" | | @now | Current time | "2026-03-27 14:22:00" | | @csentence(min, max) | Random Chinese sentence | "学中用称化置速。" | | @ctitle(min, max) | Random Chinese title | "Sample Product Name" | | @cparagraph | Random Chinese paragraph | A paragraph of random Chinese text | | @image('WxH') | Random placeholder image URL | @image('200x100') | | @pick(['a','b','c']) | Pick one item randomly from array | "b" | | @increment(1) | Auto-incrementing number (starts at 1) | 1, 2, 3... | | @string('lower', 8) | Random string | "abcdefgh" |

Generating Arrays (Bulk Data)

Append |count to a field name to generate an array:

{
  "list|5": [{ "id": "@id", "name": "@cname" }]
}

Generates a list of 5 items. Use |min-max for a random count:

{
  "list|5-10": [{ "id": "@id", "name": "@cname" }]
}

Full Syntax Categories

Prefix method names with @ when using them, e.g. @name, @integer(1, 100).

| Category | Available Methods | |----------|------------------| | Basic | boolean, natural, integer, float, character, string, range, date, time, datetime, now | | Image | image, dataImage | | Color | color | | Text | paragraph, sentence, word, title, cparagraph, csentence, cword, ctitle | | Name | first, last, name, cfirst, clast, cname | | Web | url, domain, email, ip, tld | | Address | area, region | | Helper | capitalize, upper, lower, pick, shuffle | | Misc | guid, id |

Methods prefixed with c (e.g. cname, csentence) generate Chinese content; methods without the prefix generate English content.

Full Example

/**
 * @url /api/users
 * @method GET
 */
{
  "code": 200,
  "data": {
    "total": 100,
    "list|10": [{
      "id": "@id",
      "name": "@cname",
      "age": "@integer(18, 60)",
      "email": "@email",
      "status": "@pick(['active', 'inactive', 'banned'])",
      "createdAt": "@datetime"
    }]
  },
  "message": "success"
}

Supported File Formats

The plugin automatically identifies the response type based on the file extension:

| Extension | Content-Type | Description | |-----------|--------------|-------------| | .json | application/json | JSON data, supports MockJS template syntax | | .sse | text/event-stream | SSE streaming response, supports MockJS | | .txt | text/plain | Plain text | | .html | text/html | HTML document | | .xml | application/xml | XML data | | .csv | text/csv | CSV spreadsheet data | | .md | text/markdown | Markdown document | | .css | text/css | CSS stylesheet | | .js | application/javascript | JavaScript code | | .yaml / .yml | application/x-yaml | YAML configuration | | .png | image/png | PNG image | | .jpg / .jpeg | image/jpeg | JPEG image | | .gif | image/gif | GIF image | | .svg | image/svg+xml | SVG vector image | | .pdf | application/pdf | PDF document |

Note: MockJS template syntax (e.g. @cname) currently only works in .json and .sse files. Other formats return the raw file content.


Full Format Examples

JSON Format (Most Common)

Filename: user.json

/**
 * @url /api/user/list
 * @method GET
 */
{
  "code": 200,
  "data": {
    "total": 100,
    "list|10": [{
      "id": "@id",
      "name": "@cname",
      "age": "@integer(18, 60)",
      "email": "@email",
      "createdAt": "@datetime"
    }]
  },
  "message": "success"
}

Plain Text Format

Filename: notice.txt

/**
 * @url /api/notice
 * @method GET
 */
System maintenance scheduled for tonight at 22:00, expected to last 2 hours.
Please save your work in advance!

XML Format

Filename: product.xml

/**
 * @url /api/product/detail
 * @method GET
 */
<?xml version="1.0" encoding="UTF-8"?>
<product>
  <id>1001</id>
  <name>Sample Product</name>
  <price>99.00</price>
  <stock>200</stock>
</product>

CSV Format

Filename: orders.csv

/**
 * @url /api/orders/export
 * @method GET
 */
Order ID,Customer,Product,Qty,Amount,Status
ORD001,Alice,iPhone 15,1,7999.00,Completed
ORD002,Bob,MacBook Pro,1,14999.00,Shipped
ORD003,Charlie,AirPods,2,1598.00,Pending Payment

Image Format

Filename: avatar.json (note: use a JSON file to hold the image path)

/**
 * @url /api/avatar/:id
 * @method GET
 * @content-type image/png
 */
"/absolute/path/to/your/avatar.png"

For image responses, use the @content-type annotation to declare the type. The file content should be the absolute path to the image file as a string.


Advanced Features

RESTful API — Same Path, Different Methods

For the same path, you can define responses for different HTTP methods in separate files (or the same file):

// POST /api/users → user-create.json
/**
 * @url /api/users
 * @method POST
 */
{
  "code": 200,
  "message": "Created successfully",
  "data": { "id": "@id" }
}
// GET /api/users/:id → user-detail.json
/**
 * @url /api/users/:id
 * @method GET
 */
{
  "code": 200,
  "data": {
    "id": "@id",
    "name": "@cname",
    "email": "@email"
  }
}
// PUT /api/users/:id → user-update.json
/**
 * @url /api/users/:id
 * @method PUT
 */
{ "code": 200, "message": "Updated successfully" }
// DELETE /api/users/:id → user-delete.json
/**
 * @url /api/users/:id
 * @method DELETE
 */
{ "code": 200, "message": "Deleted successfully" }

Streaming Response (SSE) — Simulate AI Typewriter Effect

Files with the .sse extension make the plugin push each item in the items array one by one, simulating streaming output.

Filename: chat.sse

/**
 * @url /api/chat/stream
 * @method POST
 */
{
  "interval": 100,
  "items|15": [{
    "id": "@increment(1)",
    "data": {
      "content": "@csentence(2, 5)"
    }
  }]
}

Field Reference:

| Field | Type | Description | |-------|------|-------------| | interval | number | Delay between messages in milliseconds. Supports MockJS expressions, e.g. "@integer(100, 500)" | | items | array | List of messages to push. Supports |count syntax for bulk generation | | items[].id | string/number | SSE message id field (optional) | | items[].event | string | SSE message event field (optional) | | items[].data | any | SSE message data field, serialized as a JSON string | | items[].retry | number | Reconnection time in ms (optional) |

Frontend example (JavaScript):

const evtSource = new EventSource("/api/chat/stream");
evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(data.content); // outputs word by word
};
evtSource.onerror = () => evtSource.close();

Framework Integration

Vite (Recommended)

See the complete example in 5-Minute Quick Start.

Core idea: use the --mode mock flag to distinguish development modes, and only start the Mock service in mock mode.

Webpack / Vue CLI

// webpack.config.js or vue.config.js
const path = require("path");
const { MockServicePlugin } = require("mock-service-plugin");

module.exports = {
  // Webpack config...
  plugins: [
    new MockServicePlugin({
      path: path.join(__dirname, "./mocks"), // path to mock folder (note: parameter is named 'path')
      port: 3008,                            // mock service port
    }),
  ],
};

For Vue CLI (vue.config.js), also configure the proxy:

// vue.config.js
const path = require("path");
const { MockServicePlugin } = require("mock-service-plugin");

module.exports = {
  configureWebpack: {
    plugins: [
      new MockServicePlugin({
        path: path.join(__dirname, "./mocks"),
        port: 3008,
      }),
    ],
  },
  devServer: {
    proxy: {
      "/api": {
        target: "http://localhost:3008",
        changeOrigin: true,
      },
    },
  },
};

React (CRA)

Using craco

// craco.config.js
const path = require("path");
const { MockServicePlugin } = require("mock-service-plugin");

module.exports = {
  webpack: {
    plugins: {
      add: [
        new MockServicePlugin({
          path: path.join(__dirname, "./mocks"),
          port: 3008,
        }),
      ],
    },
  },
};

Using customize-cra

// config-overrides.js
const path = require("path");
const { override, addWebpackPlugin } = require("customize-cra");
const { MockServicePlugin } = require("mock-service-plugin");

module.exports = override(
  addWebpackPlugin(
    new MockServicePlugin({
      path: path.join(__dirname, "./mocks"),
      port: 3008,
    })
  )
);

Debug Interface

After the Mock service starts, open the Mock service root URL (e.g. http://localhost:3008) directly in your browser to see the built-in debug interface. It shows a list of all currently registered Mock APIs, making it easy to inspect and test your routes.


FAQ

Q: I modified a mock file but the response didn't change?

The plugin supports hot reload — no service restart needed after file changes. However, your browser may have cached the old response. Try a hard refresh (Ctrl+Shift+R / Cmd+Shift+R).


Q: Getting an error Port 3008 is already in use on startup?

The mock service port is occupied. Change the port config to use a different port, and remember to update the target in your proxy configuration accordingly.

startServer({ mockDir: "./mocks", port: 3009 }); // use a different port

Q: Requests aren't matching my mock, returning 404?

Check the following:

  1. Does the @url path in the mock file exactly match the frontend request path (watch for case and trailing slashes)?
  2. Does @method match the request method (default is GET)?
  3. Is the proxy configured correctly — is the frontend request actually being forwarded to the Mock service?

Q: The same @url + @method combination is defined more than once?

The plugin will output a warning: [Mock Warn]: ... already exists and will be overwritten. The later definition will overwrite the earlier one. Make sure each API is only defined once.


Q: MockJS placeholders like @cname and @email aren't working?

MockJS template syntax currently only works in .json and .sse files. Other formats (.txt, .xml, etc.) return the raw file content.


Q: How do I check whether the app is in mock mode in code?

Typically you distinguish modes via environment variables. In a Vite project, you can use a .env.mock file:

# .env.mock
VITE_API_BASE_URL=http://localhost:3008
// in your code
const apiBase = import.meta.env.VITE_API_BASE_URL || "/api";

Example Projects


Contributing

Issues and Pull Requests are welcome.

License

MIT