当前位置: 代码网 > it编程>编程语言>Javascript > 在react项目中webpack使用mock数据的操作方法

在react项目中webpack使用mock数据的操作方法

2024年07月05日 Javascript 我要评论
1. 创建react项目使用 create-react-app 创建项目npx create-react-app react-mock执行 eject 命令npm run eject删除 packag

1. 创建react项目

使用 create-react-app 创建项目

npx create-react-app react-mock

执行 eject 命令

npm run eject

 删除 package.json 文件中的 eslintconfig 选项

2. 安装依赖包

npm i path-to-regexp fast-glob chokidar axios

3. 创建中间件

在 config 文件夹中创建 webpackmiddlewaremock.js 文件

让webpack-dev-server加载中间件,把mock配置文件的请求地址和响应数据映射到dev server的路由上

const { pathtoregexp } = require("path-to-regexp");
const fg = require("fast-glob");
const path = require("path");
const chokidar = require("chokidar");
const valid_methods = [
  "get",
  "post",
  "put",
  "delete",
  "patch",
  "head",
  "options",
];
const default_method = "get";
const mock_file_pattern = "mock/**/*.{js,ts}";
const default_options = {
  rootdir: "",
  exclude: [],
};
class webpackmiddlewaremock {
  constructor(options = {}) {
    this.options = { ...default_options, ...options };
    const { rootdir, exclude } = this.options;
    this.mockconfigs = this.getconfigs(rootdir, exclude);
  }
  parsemockkey(key) {
    const keyitems = key.split(/\s+/);
    if (keyitems.length === 1) {
      return {
        method: default_method,
        path: keyitems[0],
      };
    } else {
      const [method, path] = keyitems;
      const uppercasemethod = method.tolocaleuppercase();
      if (!valid_methods.includes(uppercasemethod)) {
        console.error(`method ${method} is not supported`);
      }
      if (!path) {
        console.error(`${key} path is not defined`);
      }
      return {
        method,
        path,
      };
    }
  }
  getconfigs(rootdir, exclude) {
    const ignore = exclude.map(
      (ele) => `mock${ele.startswith("/") ? "" : "/"}${ele}`
    );
    const mockfiles = fg
      .sync(mock_file_pattern, {
        cwd: rootdir,
        ignore,
      })
      .map((file) => path.join(rootdir, file));
    const mockconfigs = [];
    mockfiles.foreach((mockfile) => {
      // disable require cache
      delete require.cache[mockfile];
      let mockmodule;
      try {
        mockmodule = require(mockfile);
      } catch (error) {
        console.error(`failed to parse mock file ${mockfile}`);
        console.error(error);
        return;
      }
      const config = mockmodule.default || mockmodule || {};
      for (const key of object.keys(config)) {
        const { method, path } = this.parsemockkey(key);
        const handler = config[key];
        if (
          !(
            typeof handler === "function" ||
            typeof handler === "object" ||
            typeof handler === "string"
          )
        ) {
          console.error(
            `mock value of ${key} should be function or object or string, but got ${typeof handler}`
          );
        }
        mockconfigs.push({
          method,
          path,
          handler,
        });
      }
    });
    return mockconfigs;
  }
  matchpath(req, mockconfigs) {
    for (const mockconfig of mockconfigs) {
      const keys = [];
      if (req.method.tolocaleuppercase() === mockconfig.method) {
        const re = pathtoregexp(mockconfig.path, keys);
        const match = re.exec(req.path);
        if (re.exec(req.path)) {
          return {
            keys,
            match,
            mockconfig,
          };
        }
      }
    }
  }
  decodeparam(val) {
    if (typeof val !== "string" || val.length === 0) {
      return val;
    }
    try {
      return decodeuricomponent(val);
    } catch (error) {
      if (error instanceof urierror) {
        error.message = `failed to decode param ' ${val} '`;
        error.status = 400;
        error.statuscode = 400;
      }
      throw error;
    }
  }
  createwatch() {
    const watchdir = this.options.rootdir;
    const watcher = chokidar
      .watch(watchdir, {
        ignoreinitial: true,
        ignored: [/node_modules/],
      })
      .on("all", () => {
        const { rootdir, exclude } = this.options;
        this.mockconfigs = this.getconfigs(rootdir, exclude);
      });
    return watcher;
  }
  createmiddleware() {
    const middleware = (req, res, next) => {
      const matchresult = this.matchpath(req, this.mockconfigs);
      if (matchresult) {
        const { match, mockconfig, keys } = matchresult;
        const { handler } = mockconfig;
        if (typeof handler === "function") {
          const params = {};
          for (let i = 1; i < match.length; i += 1) {
            const key = keys[i - 1];
            const prop = key.name;
            const val = this.decodeparam(match[i]);
            if (val !== undefined) {
              params[prop] = val;
            }
          }
          req.params = params;
          handler(req, res, next);
          return;
        } else {
          return res.status(200).json(handler);
        }
      } else {
        next();
      }
    };
    this.createwatch();
    return {
      name: "mock",
      middleware: middleware,
    };
  }
  static use(options) {
    const instance = new webpackmiddlewaremock(options);
    const middleware = instance.createmiddleware();
    return middleware;
  }
}
module.exports = webpackmiddlewaremock;

4. 修改webpackdevserver

修改 config/webpackdevserver.config.js 文件

引入 webpackmiddlewaremock 中间件

const webpackmiddlewaremock = require("./webpackmiddlewaremock");

删除 onbeforesetupmiddleware 和 onaftersetupmiddleware 选项,替换 setupmiddlewares 选项

    setupmiddlewares: (middlewares, devserver) => {
      const mockmiddleware = webpackmiddlewaremock.use({
        rootdir: paths.apppath,
      });
      middlewares.unshift(mockmiddleware);
      return middlewares;
    },

在项目根目录创建 mock 文件夹,并创建 user.js 文件

module.exports = {
  // 返回值是 string 类型
  "get /api/name": "tom",
  // 返回值 array 类型
  "post /api/users": [
    { name: "foo", id: 0 },
    { name: "bar", id: 1 },
  ],
  "get /api/users/:id": (req, res) => {
    res.send({
      params: req.params,
    });
  },
  // 返回值是 object 类型
  "delete /api/users/1": { name: "bar", id: 1 },
};

5. 测试mock请求

修改 app.js 文件

import { usestate } from "react";
import axios from "axios";
function app() {
  const [resultget, setresultget] = usestate("");
  const [resultpost, setresultpost] = usestate("");
  const [resultparams, setresultparams] = usestate("");
  const [resultdelete, setresultdelete] = usestate("");
  const handleget = async () => {
    const res = await axios.get("/api/name");
    setresultget(res.data);
  };
  const handlepost = async () => {
    const res = await axios.post("/api/users");
    setresultpost(json.stringify(res.data));
  };
  const handleparams = async () => {
    const res = await axios.get("/api/users/100");
    setresultparams(json.stringify(res.data));
  };
  const handledelete = async () => {
    const res = await axios.delete("/api/users/1");
    setresultdelete(json.stringify(res.data));
  };
  return (
    <div classname="app">
      <button onclick={handleget}>"get /api/name"</button>
      <h2>{resultget}</h2>
      <hr />
      <button onclick={handlepost}>"post /api/users"</button>
      <h2>{resultpost}</h2>
      <hr />
      <button onclick={handleparams}>"get /api/users/:id"</button>
      <h2>{resultparams}</h2>
      <hr />
      <button onclick={handledelete}>"delete /api/users/1"</button>
      <h2>{resultdelete}</h2>
      <hr />
    </div>
  );
}
export default app;

启动项目测试

到此这篇关于在react项目中让webpack使用mock数据的文章就介绍到这了,更多相关react项目webpack使用mock数据内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com