日常业务开发,会频繁请求接口,非常耽误功夫。一个简单的方法是把数据缓存起来,然而我并不想每次提交前还要关心缓存数据是否被移除。
所以,要实现:
- 将数据复制到项目文件夹中,名字就叫 apiMock.js,不限文件个数和位置;
- 无侵入、不影响打包;
项目环境(重要)
vue-cli3、webapck4
webpack require.context
require.context 是一个非常有用但经常被忽略的 api,可以用它来加载任意模块:
// 1. 获取 src 文件夹下所有的 apiMock.js 文件
const mockDataContext = require.context("@src", true, /apiMock.js$/);
// 2. 获取所有文件的内容,并保存到 mockDataMap 对象中
const mockDataMap = mockDataContext.keys().reduce((map, key) => {
Object.assign(map, mockDataContext(key).default);
return map;
}, {});
terser vue-cli3 所用的 js 解析、混淆、压缩器
terser 默认可以删除 unreachable code,譬如,对于如下代码:
var a = 1
if (false) {
a = 2
}
经过 terser 处理后,if 代码块会被移除,只剩下var a = 1
。
实施
有了上面的铺垫,实施起来就比价容易了。
首先,在项目最外层文件夹新建 .env.local 文件(它会被 git 忽略),添加:VUE_APP_MOCk=1
;
然后,修改 vue.config.js:
...
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
VUE_APP_MOCK: !!process.env.VUE_APP_MOCk
})
]
},
...
```
最后包装项目的 fetch/axios:
````js
import request from "axios";
export const fetch = (() => {
let requestFlight = request;
// 全局注入进来的
if (VUE_APP_MOCK) {
const mockDataContext = require.context("@src", true, /apiMock.js$/);
// mockDataMap 包含了所有存在 apiMock.js 文件中的数据
const mockDataMap = mockDataContext.keys().reduce((map, key) => {
Object.assign(map, mockDataContext(key).default);
return map;
}, {});
requestFlight = (params, ...args) => {
// 【注意!!!】
// 这里会得到本地文件的数据,具体存取策略需要结合项目综合考量
const data = mockDataMap["r" + params.pid];
if (!data) return request(params, ...args);
return new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, 1000);
});
};
}
return requestFlight;
})();
使用
apiMock.js
export default {
r4507: {res: {...}}
}
fetch({pid: "4507"})
.then(res => {
// res 为本地数据
console.log(res)
})
fetch({pid: "4508"})
.then(res => {
// 本地没有 4508 的缓存,所以 res 为接口返回的数据
console.log(res)
})