前端真实mock数据解决方案

794 阅读2分钟

故事背景
我们在项目完成之后,有时候会有一些小的调整,比如:文案的修改,fixbug,很小的功能调整。 为了完成这个功能调整我们一般来说需要三步:

  1. 账号登录系统
  2. 跳转相应的功能页面
  3. 查看返回的数据结构 产生的问题
    寻找账号很费时间,找到了,还不一定有这个权限。不同的账号,可能数据结构有差异,更有的时候,开发环境突然清库,发现没有任何数据,因此还是很难得到我们想要的数据
    原因分析
    开发环境的不稳定(数据经常丢失),没有一个大而全的账号(通常情况下账号有些功能是互拆的)。
    解决方案
    我们想要的无非是后端返回的数据结构,因此我们只要应对每一个api接口给一份完整的数据结构就行了。 大致思路就是:在webpack就行api代理的时候实时的copy一份数据生成到当前的mock文件夹中,文件名当前是根据apiurl生成,这样就保证了生成数据的唯一性,下次mock访问相同规则直接提取
const fs = require('fs-extra');
const path = require('path');
const zlib = require('zlib');
/**
 * 判断文件存不存在,不存在就新建
 */
function getFilePath(url) {
  const filename = url.split('/').filter(str => str).join('_');
  return path.join(__dirname, '../mock/', filename + '.json');
}
async function generateMockDataByUrl(url, data) {
  const filePath = getFilePath(url);
  const exists = await fs.pathExists(filePath);
  try {
    if (!exists) {
      await fs.outputJsonSync(filePath, JSON.parse(data), {
        spaces: 2
      });
    }
  } catch (error) {
    console.log(data);
  }

}
async function getDataFromMockByUrl(url) {
  const filePath = getFilePath(url);
  const exists = await fs.pathExists(filePath);

  if (exists) {
    return fs.readJson(filePath);
  }

  return JSON.stringify([]);
}
function unZip(data) {
  return new Promise((resolve, reject) => {
    zlib.gunzip(data, function (err, buffer) {
      if (err) {
        reject(err);
      }
      resolve(buffer.toString());
    });
  });
}
// 设置headers
function setHeaders(originHeaders, targetHeaders) {
  Object.keys(originHeaders).forEach(key => {
    targetHeaders.setHeader(key, originHeaders[key]);
  });
}
module.exports = function(app) {
  app.use(
    ['/idgate', '/login'],
    createProxyMiddleware({
      changeOrigin: true,
      target: ''
      selfHandleResponse: true,
      async onProxyReq(proxyReq, req, res) {
        proxyReq.setHeader('host', req.headers.host);
        // 启用 mock 方案
        if (isMock) {
          setHeaders(
            {
            ...req.headers,
            'content-type': 'application/json;charset=UTF-8'
            }, res);
          const data = await getDataFromMockByUrl(req.url);
          return res.send(data);
        }
      },
      async onProxyRes(proxyRes, req, res) {
        if (!isMock) {
          setHeaders(proxyRes.headers, res);
        }
        let body = [];
        proxyRes.on('data', function (chunk) {
            body.push(chunk);
        });
        proxyRes.on('end', async function () {
          body = Buffer.concat(body);
          // 这里需要判断header content-encoding编码格式 进一步处理
          if (proxyRes.headers['content-encoding'] === 'gzip') {
            const data = await unZip(body);
            await generateMockDataByUrl(req.url, data);
          } else {
            // 这个方案需要和后端联调 存在多种编码格式 gzip defate ....
            await generateMockDataByUrl(req.url, body.toString());
          }
          res.end(body);
        });
      }
    })
  );
};

结论
所有数据完全真实,账号导致的差异,我们可以本地修改对应字段,基本能够解决寻找账号的尴尬。
最后 欢迎大家一起讨论更好的方案~。