背景

现在前后端分离的项目很常见,当服务端接口在开发中时,前端要怎么调试接口尼,为了解决这个问题,模拟服务端接口应运而生,webapck-plugin-mock 就是一个模拟服务端接口的webpack插件,配置起来简单,容易上手,且mock数据支持多种格式

源码(talk is cheap , show me the code)

class WebpackPluginMock {
  private readonly config: MockServerConfig
  constructor(config: MockServerConfig) {
    this.config = config
  }

  apply() {
    serve(this.config)
  }
}

module.exports = WebpackPluginMock
const serve = async (config: MockServerConfig) => {
  const app = new Koa();
  const router = new Router();
  // const upload = multer();

  const __DEV__ = process.env.NODE_ENV === 'development';
  const publicBasePath = path.resolve(__dirname, '../public');

  __DEV__ && console.log('[mock] config', config);

  jsonp(app, {
    callback: 'callback',
    limit: 50,
  });

  /**
   * logger 最外层调用
   * json pretty 次外层,方便格式化 response
   * cors 次次外层,收到请求优先处理 CORS
   * 先调用 koa-body 再调用 koa-router
   */
  app.use(logger());
  if (config.pretty) {
    app.use(
      json({
        pretty: true,
        spaces: 2,
      })
    );
  }
  app.use(
    cors({
      credentials: true,
    })
  );
  app.use(
    koaBody({
      multipart: true,
    })
  );
  app.use(router.routes());
  app.use(router.allowedMethods());
  app.use(koaStatic(publicBasePath));

  addInternalRoutes(router);

  try {
    // 自动扫描 apis 文件夹下 JS、JSON,添加为 route
    const { jsPaths, jsonPaths } = await scanRoutes(config.apiBasePath);
    registerRoutes(router, {
      rootPath: config.apiBasePath,
      jsPaths,
      jsonPaths,
    });
  } catch (err) {
    logError(err);
  }

  /**
   * apis 文件变化回调
   */
  const onRoutesChange = async (filePath: string) => {
    const { jsPaths, jsonPaths } = await scanRoutes(filePath);
    const routePaths = [...jsPaths, ...jsonPaths];
    routePaths.forEach(routePath => {
      logWarning(
        `[onRoutesChange] "${require.resolve(routePath)}" will be reload`
      );
      delete require.cache[require.resolve(routePath)];
    });
    registerRoutes(router, {
      rootPath: config.apiBasePath,
      jsPaths,
      jsonPaths,
    });
  };

  const onRoutesChangeDebounced = debounce(onRoutesChange, 1000);

  // 监控 apis 文件变化
  if (config.watch) {
    logSuccess(`[mock] Watch "${config.apiBasePath}"`);
    watchRoutes(config.apiBasePath, onRoutesChangeDebounced);
  }

  app.on('error', (err, ctx) => {
    logError('[mock] server error', err, ctx);
  });

  app.listen(config.port);

  logSuccess(`[mock] Mock server is running at ${config.port}`);
  logSuccess(`[mock] LOCAL http://localhost:${config.port}`);
  logSuccess(`[mock] LAN  http://${address.ip()}:${config.port}`);

  return {
    app,
    router,
  };
};

export { serve }

安装

# npm
npm install webpack-plugin-mock -D

# yarn
yarn add webpack-plugin-mock -D

配置

new WebpackPluginMock({
  apiBasePath: './mock',
  watch: true,
  pretty: true,
  port: 8090
})

项目根目录建mock -> user -> list.json

{
  "code": 0,
  "msg": "",
  "data": {
    "dataList|10" :[
      {
        "id": "@id",
        "name": "@cname",
        "phone": "@pick([13913998972, 19941558406])",
        "deptName": "前端开发部"
      }
    ],
    "totalCount": 20,
    "totalPageCount": 2
  }
}

启动项目

npm run dev
.....
[mock] Watch "./mock"
[mock] Mock server is running at 8090
[mock] LOCAL http://localhost:8090
[mock] LAN  http://10.46.85.40:8090
[mock] api list http://10.46.85.40:8090/mock-api/list
....
webpack 5.72.1 compiled successfully in 10882 ms

效果

在这里插入图片描述