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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@bigbigbird/mock

v5.0.9

Published

前端mock调试

Downloads

13

Readme

birdmock

使用 nodejs 的原生 http/https 模块,结合 mockjs 开发的本地 mock 服务

  • 不依赖 Webpack 等构建开发工具,可以独立在本地运行 http/https 服务;
  • 支持自定义响应数据、静态资源获取、上传文件、跨域、https 请求和日志打印;
  • 支持为 http/https 请求 mock 数据配置延迟响应时间;
  • 支持通过 rawResponse 函数对外提供 nodejs 的请求和响应接口;
  • 支持正向代理,即从本地启动的服务代理到目标服务;
  • 支持配置其他开发工具的 proxy 代理到 birdmock 启动的服务;

P.s. mockjs 版本为 1.1.0,mock 数据支持 mockjs 的内置语法。

安装


使用 npm 安装

npm i @bigbigbird/mock -D

使用 yarn 安装

yarn add @bigbigbird/mock -D

使用


启动默认的 mock 服务

修改 package.json 中的 scripts 配置。

"scripts": {
  "mock": "birdmock"
}

执行上述命令

npm run mock

执行命令后,会根据默认配置启动 mock 服务,如果服务启动成功,则终端会打印如下内容。

=====代理模式已启动=====
{ /api => http://127.0.0.1:4201 }

并且在启动 mock 服务之前,会自动地在项目根目录生成 birdmock 文件夹,其目录结构如下。

 -项目根路径
 -birdmock
    -assets         # 静态资源目录
    -logs           # 日志目录
    -mocks          # mock文件目录
    -upload         # 文件上传目录
    -config.js      # birdmock配置文件

birdmock 的默认配置在 birdmock/config.js 中。

'use strict';
module.exports = {
  // 修改 mock 文件时重启服务的防抖时间
  watchDebounceTime: 2000,
  // 日志是否格式化响应的json
  parseJSON: false,
  // 本地服务,协议设置为 https 则将开启 https 服务
  server: 'localhost:4201',
  // 可选代理服务(可通过server服务代理到目标服务)
  proxy: {
    '/api': {
      target: 'http://127.0.0.1:4201',
      changeOrigin: true,
      rewrite: function (url) {
        return url;
      },
    },
    '/ipa': {
      target: 'http://127.0.0.1:4202',
      changeOrigin: true,
      rewrite: function (url) {
        return url;
      },
    },
  },
  // 可选跨域配置
  cors: {
    // 源服务,默认值:'*'
    origin: '*',
    // 允许的请求头字段,默认值:'*'
    headers: '*',
    // 允许的请求方法,默认值:'*'
    methods: '*',
    // 是否允许跨域携带 cookie
    // 如果需要跨域携带 cookie ,则上述默认值不能设置为'*'
    credentials: 'false',
  },
};

启动简单的 mock 服务

默认启动的 mock 服务会将以 /api 开头的接口代理转发到自身,一般开发的时候不需要这么做,应该是代理到后端的服务地址,这里是为了兼容“可以代理到自身服务”的使用场景。所以,如果不需要代理和跨域请求,一个简单地配置应该是这样的。

module.exports = {
  // 修改配置文件或 mock 文件时,重启 mock 服务的防抖时间
  watchDebounceTime: 2000,
  // 日志是否格式化响应的 json 数据
  parseJSON: false,
  // 本地服务地址,协议设置为 https 则将开启 https 服务
  server: 'http://localhost:4201',
};

在修改配置文件后,mock 服务会自动地进行重启,并在控制台打印如下内容。

服务器重启中...
=====本地模式已启动{/ => http://localhost:4201} { 接口数量:6 }=====

P.s. 配置 server 为 https 协议的时候,因为本地 mock 服务证书未颁发,故本地 https 请求会提示连接不安全,这个不影响本地开发使用。

启动代理 mock 服务

在配置文件中加上 proxy 配置

module.exports = {
  // 修改配置文件或 mock 文件时,重启 mock 服务的防抖时间
  watchDebounceTime: 2000,
  // 日志是否格式化响应的 json 数据
  parseJSON: false,
  // 本地服务地址,协议设置为 https 则将开启 https 服务
  server: 'http://localhost:4201',
  // 代理配置
  proxy: {
    '/api': {
      // 这里应修改为你实际要代理的目标服务地址
      target: 'http://127.0.0.1:4201',
      changeOrigin: true,
      rewrite: function (url) {
        return url;
      },
    },
    '/ipa': {
      // 这里应修改为你实际要代理的目标服务地址
      target: 'http://127.0.0.1:4202',
      changeOrigin: true,
      rewrite: function (url) {
        return url;
      },
    },
  },
};

还可以直接从命令行配置代理,但这种方式只能配置一个代理,没有使用配置文件灵活。在 package.json 的 scripts 中添加如下命令。

"scripts": {
  "mock:proxy": "cross-env target=localhost:4202 pathRewrite='^/api':'/ipa' changeOrigin=true birdmock"
}

从命令行启动这个本地代理服务

npm run mock:proxy

P.s. 上述 pathRewrite表示会将接口匹配正则^/api的字符串替换为/ipa,这和配置文件中的rewrite配置不同,rewrite 函数会将请求接口重写为执行后的返回值。

请求静态资源

如果接口需要请求静态资源,则应事先在 birdmock/assets 目录下放置对应的静态资源,然后在 mock 文件中按照 mock 文件示例来注册请求静态资源的接口。

mock 文件

mock 文件存放在 birdmock/mocks 目录下,该目录下所有以 .js 结尾的文件所导出的键值对对象都会被注册到 mock 服务的 mock 数据中,mock 文件示例如下。

module.exports = {
  // 根据参数返回不同数据,并通过 delay 配置延迟响应时间,真正响应的是 data 对象
  '/example': function (params) {
    var id = params.id;
    if (id == 1) {
      // 延时3s返回
      return {
        delay: 3000,
        data: {
          content: '我是示例mock返回的数据1',
        },
      };
    } else if (id == 2) {
      // 无延时返回
      return {
        content: '我是示例mock返回的数据2',
      };
    }
  },
  // 通配符匹配接口,并通过 delay 配置延迟响应时间,真正响应的是 data 对象
  '/api/*': function (params = {}) {
    return {
      delay: parseInt(params.delay),
      data: {
        mock: 'birdmock',
      },
    };
  },
  // 请求静态资源,带.xxx后缀
  '/static/test/bird.svg': function () {
    return fs.readFileSync(resolve('../assets/bird.svg'));
  },
  // 请求静态资源,不带.xxx后缀
  '/test/bird': function () {
    return {
      filename: 'bird.svg',
      buffer: fs.readFileSync(resolve('../assets/bird.svg')),
    };
  },
  // 上传文件
  '/upload/file': function (files) {
    console.log(files, '参数');
    var fileArr = files.file; // file 为formData的字段名
    var paths = [];
    fileArr.forEach(function (f) {
      var path = f.path;
      paths.push(path);
    });
    return {
      paths: paths,
    };
  },
  // 通过调用 nodejs 的请求和响应接口来响应请求
  '/diy/rawResponse': {
    rawResponse: function (req, res, requestParams) {
      res.setHeader('content-type', 'text/plain');
      res.end('Hello Word!');
    },
  },
};

只要接口地址匹配到了如上述 mock 数据中的“键”,则会返回该键所对应的值:

  • 值为普通对象时,nodejs 的 response 对象会将其作为响应数据响应给发起请求的客户端;
  • 值为函数时,会将请求参数作为函数的入参,执行该函数后将返回值作为响应数据响应给发起请求的客户端

值遵循如下规则:

  • 如果不需要配置延迟响应和改变响应状态码,则返回的值即为响应数据,如:对象{xxx: 'yyy'} 或其他基本类型;
  • 如果需要配置延迟响应时间 ,则值的正确结构为{delay: 2000, data: {...xxx}},其中 delay 为延迟时间,data 为真正要响应的数据;
  • 如果需要改变响应状态码 ,则值的正确结构为{statusCode: 403, data: {...xxx}},其中 statusCode 为状态码,data 为真正要响应的数据;
  • 真正的响应数据支持 mockjs 的内置语法,详情参考 Mock 官方文档

使用示例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      var baseUrl = 'http://localhost:4201';
      var qs = {
        stringify: params => {
          var arr = [];
          Object.keys(params).forEach(k => {
            arr.push(`${k}=${params[k]}`);
          });
          return arr.join('&');
        },
      };

      function print(xhr) {
        switch (xhr.responseType) {
          case 'json':
            console.log(
              `${xhr.responseURL}:`,
              JSON.stringify(xhr.response, null, 2)
            );
            return;
          case 'text':
          default:
            console.log(`${xhr.responseURL}:`, xhr.response);
        }
      }

      function request({
        method = 'GET',
        url,
        headers,
        responseType = 'json',
        params,
      }) {
        var xhr = new XMLHttpRequest();
        var src = `${baseUrl}${url}`;

        if (params) {
          switch (method.toUpperCase()) {
            case 'GET':
            case 'DELETE':
              params = qs.stringify(params);
              src += `?${params}`;
              break;
            case 'POST':
            case 'PUT':
              // json
              if (headers && headers['content-type'].indexOf('json') > -1) {
                params = JSON.stringify(params);
                break;
              }
              // 非 json
              if (!headers) headers = {};
              headers['content-type'] = 'application/x-www-form-urlencoded';
              params = qs.stringify(params);
              break;
          }
        }

        xhr.responseType = responseType;
        xhr.open(method, src, true);

        if (headers) {
          Object.keys(headers).forEach(k => {
            xhr.setRequestHeader(k, headers[k]);
          });
        }

        xhr.send(params);
        return new Promise(resolve => {
          xhr.onload = () => {
            resolve(xhr);
          };
        });
      }

      request({
        url: '/api/example',
        params: { delay: 5000 },
      }).then(print);

      request({
        url: '/static/test/bird.svg',
        responseType: 'text',
      })
        .then(xhr => {
          document.body.innerHTML = xhr.responseText;
          return xhr;
        })
        .then(print);

      request({
        url: '/diy/rawResponse',
        responseType: 'text',
      }).then(print);

      request({
        url: '/ipa/example',
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        params: { c: 3, d: 4 },
      }).then(print);
    </script>
  </body>
</html>

问题反馈


issue

https://github.com/zhangzhipeng-git/birdmock-ts/issues/new

email

[email protected]