Develop a tool that generates interface files automatically and mocks them
Pain points are:
- Write interface API file (as follows), more trouble. Most of the interfaces are in the same format, either GET or POST. I’m doing it over and over again.
- Following the DRY (Don’t Repeat Yourself) principle, we tried to automate this
// This is an API file that needs to be written repeatedly each time import { axios } from './myAxios.js' export const xxxxList = (data) = > { return axios({ method: 'post'.url: '/xxx/xxx', data }) } export const xxxxupdate = (data) = > { return axios({ method: 'post'.url: '/xxx/xx', data }) } export const xxxx = (params) = > { return axios({ method: 'get'.url: '/xxxx/xxxx', params }) } Copy the code
Try to automate this with tools
Functional requirements
- The interface file can be automatically generated
- And mock
- And the group members can easily use it
Design idea:
Generate the corresponding interface file from a configuration file (such as fe.config.js) in the project root directory and mock it
- The configuration file is as follows
// fe.config.js
module.exports = {
// apiAndMock: This applies to the module of apiAndMock. Other tools have their keys
apiAndMock: {
config: { // The corresponding API file will be generated automatically based on the object here
reportList: { // ReportList.js is generated (n keys are generated, n keys are generated)
getReportList: {
url: '/getReportList',},addReport: {
url: '/addReport'.method: 'post' // Data is processed automatically
},
updateReport: {
url: '/updateReport'.method: 'post' // Data is processed automatically
},
deleteReports: {
url: '/deleteReports'.method: 'post' // Data is processed automatically
}
}
}
}
}
Copy the code
The difficulties in
-
Difficulty 1: Users might wrap AXIos (or others), for example by adding request interception or response interception (such as doing some authentication).
- At this point, the current project needs to use axiOS wrapped by the user.
- Workaround: Add a configuration item myAxios as follows.You are advised to write an alias @ that represents the SRC directory
- You also need to add myAxiosInstance, because some projects import instance directly and you can use it, but others require instance.instance
module.exports = { apiAndMock: { + myAxios: "import instance from '@/axios/index.js'".// We recommend an alias @, representing the SRC directory, + myAxiosInstance: 'instance.instance'.config: { // The corresponding API file will be generated automatically based on the object here reportList: { // ReportList.js is generated (n keys are generated, n keys are generated). }}}}Copy the code
What is wrapped Axios?
-
For example: here’s axios/index.js in my project, also wrapped axios
// axios/index.js.// Create an axios instance const instance = axios.create({ ... }) // Add request interceptor instance.interceptors.request.use(function (config) {...return config }, function (error) {... })// Add a response interceptor instance.interceptors.response.use(function (response) {...return response }, function (error) {... })/ / initialization function install (Vue, opt) { // Add global methods Vue.prototype.$axios = instance } export default { install, instance } Copy the code
-
Difficulty 2: It is also a requirement point, and I hope to complete the mock function together
Add a data field, which will be used in mock mode, without affecting interface files
module.exports = { // apiAndMock: This applies to the module of apiAndMock. Other tools have their keys apiAndMock: { myAxios: "import instance from '@/axios/index.js'".// We recommend an alias @, representing the SRC directory, myAxiosInstance: 'instance.instance'.config: { // The corresponding API file will be generated automatically based on the object here reportList: { // ReportList.js is generated (n keys are generated, n keys are generated) getReportList: { url: '/getReportList', + data: [ // The data here is used for mock generation + { + id: 1, + reportName: '234', + reportTitle: '33423', + topicIds: '24 31', + status: 0, + startDate: '2020-11-01', + lateDays: 5, + createUser: 'xxx.li', + updateUser: 'xx.li', + createTime: 'the 2020-11-18 14:04:17', + updateTime: 'the 2020-11-18 14:04:17' + }, + { + id: 2, + reportName: '234', + reportTitle: '33423', + topicIds: '24 31', + status: 0, + startDate: '2020-11-01', + lateDays: 5, + createUser: 'xxx.li', + updateUser: 'xx.li', + createTime: 'the 2020-11-18 14:04:17', + updateTime: 'the 2020-11-18 14:04:17'+} +]},addReport: { url: '/addReport'.method: 'post' // Data is processed automatically }, updateReport: { url: '/updateReport'.method: 'post' // Data is processed automatically }, deleteReports: { url: '/deleteReports'.method: 'post' // Data is processed automatically } } } } } Copy the code
The specific implementation is explained below
-
Difficulty 3: All the team members can use it easily
Solution: We need to use our tool platform to build the internal front end tool platform
NPM install -g@company /feTools
The command must be executed in the root directory // 2. The fe.config.js configuration file must be prepared in advance. Mock // mock pattern fe API // MOCK pattern fe api-pkg // API pattern fe api-pkg // API pattern fe mock // mock pattern fe api-pkg // API pattern fe api-pkg // Compatible with some old projects)Copy the code
Difficulty 2: How to implement the Mock function
- First, how does the mock function work
- Consider automating the mock functionality
1. How is the mock function implemented first
Just introduce myMock/index.js anywhere to make your mock work
- Use the axios-mock-adapter library, which intercepts the axios request and responds with the corresponding data if the path matches (see configuration below).
The mock folder directory structure is as follows: myMock Reportlist.js index.js Just introduce myMock/index.js anywhere to make your mock work// index.js
var axios = require("axios")
// Use the mock library, which intercepts the axios request and responds with the corresponding data if the path matches (see configuration below).
var MockAdapter = require("axios-mock-adapter")
var mock = new MockAdapter(axios)
import { init as reportList } from './reportList' // Introduce the mock response file
reportList(mock)
// reportList.js
export const init = (mock) = > {
mock.onGet('/getReportList').reply(200, {
data: [{"id":1."reportName":"xxx new"."reportTitle":"xxxx"."topicIds":"24 31"."status":0."startDate":"2020-11-01"."lateDays":5."createUser":"xxxx.li"."updateUser":"xxxx.li"."createTime":"The 2020-11-18 14:04:17"."updateTime":"The 2020-11-18 14:04:17"},
{"id":2."reportName":"xxx new"."reportTitle":"xxxx"."topicIds":"24 31"."status":0."startDate":"2020-11-01"."lateDays":5."createUser":"xxxx.li"."updateUser":"xxxx.li"."createTime":"The 2020-11-18 14:04:17"."updateTime":"The 2020-11-18 14:04:17"}].ret: 0.msg: 'ok'
})
mock.onPost('/addReport').reply(200, {
data: [].ret: 0.msg: 'ok'
})
mock.onPost('/updateReport').reply(200, {
data: [].ret: 0.msg: 'ok'
})
mock.onPost('/deleteReports').reply(200, {
data: [].ret: 0.msg: 'ok'})}Copy the code
2. Thinking about automating the mock feature
With the reference text above, it can be easily implemented in conjunction with the configuration file
Paste the final result according to the configuration file
Configuration file: fe.config.js
// fe.config.js
module.exports = {
// apiAndMock: This applies to the module of apiAndMock. Other tools have their keys
apiAndMock: {
myAxios: "import instance from '@/axios/index.js'".// We recommend an alias @, representing the SRC directory,
myAxiosInstance: 'instance.instance'.config: { // The corresponding API file will be generated automatically based on the object here
reportList: { // ReportList.js is generated (n keys are generated, n keys are generated)
getReportList: {
url: '/getReportList'.data: [ // The data here is used for mock generation
{
id: 1.reportName: '234'.reportTitle: '33423'.topicIds: '24 31'.status: 0.startDate: '2020-11-01'.lateDays: 5.createUser: 'xxx.li'.updateUser: 'xx.li'.createTime: 'the 2020-11-18 14:04:17'.updateTime: 'the 2020-11-18 14:04:17'
},
{
id: 2.reportName: '234'.reportTitle: '33423'.topicIds: '24 31'.status: 0.startDate: '2020-11-01'.lateDays: 5.createUser: 'xxx.li'.updateUser: 'xx.li'.createTime: 'the 2020-11-18 14:04:17'.updateTime: 'the 2020-11-18 14:04:17'}},addReport: {
url: '/addReport'.method: 'post' // Data is processed automatically
},
updateReport: {
url: '/updateReport'.method: 'post' // Data is processed automatically
},
deleteReports: {
url: '/deleteReports'.method: 'post' // Data is processed automatically
}
}
}
}
}
Copy the code
Results obtained:
// Directory structure
api
myApi
myAxios.js // There are two cases of this file: mock mode and API mode
reportList.js
myMock
index.js
reportList.js
// myApi/ myaxios.js this file has two cases, one is mock mode, the other is API mode
// fe mock is a mock pattern that introduces mock files
/* This file is automatically generated and changes will not take effect */
import axiosRoot from 'axios' // Use the default axios
import '.. /myMock' // Mock files are introduced
export const axios = (obj) = > {
return new Promise((resolve, reject) = > {
axiosRoot(obj)
.then(e= > {
resolve(e && e.data)
})
.catch(err= > {
console.error('Interface return error:' + JSON.stringify(err))
reject(err)
})
})
}
console.log('Currently in mock mode')
// fe api-pkg is an API pattern that does not introduce mock files, but a user-wrapped axios instance
/* This file is automatically generated and changes will not take effect */
import instance from '@/axios/index.js'
export const axios = (obj) = > {
return new Promise((resolve, reject) = > {
instance.instance(obj)
.then(e= > {
resolve(e && e.data)
})
.catch(err= > {
console.error('Interface return error:' + JSON.stringify(err))
reject(err)
})
})
}
// myApi/reportList.js
/* This file is automatically generated, the modification will not take effect, the modification entry: fe.config.js */
import { axios } from './myAxios.js'
export const getReportList = (params) = > {
return axios({
method: 'get'.url: '/getReportList',
params
})
}
export const addReport = (data) = > {
return axios({
method: 'post'.url: '/addReport',
data
})
}
export const updateReport = (data) = > {
return axios({
method: 'post'.url: '/updateReport',
data
})
}
export const deleteReports = (data) = > {
return axios({
method: 'post'.url: '/deleteReports',
data
})
}
// myMock/index.js
/* This file is automatically generated, the modification will not take effect, the modification entry: fe.config.js */
var axios = require("axios")
var MockAdapter = require("axios-mock-adapter")
var mock = new MockAdapter(axios)
import { init as reportList } from './reportList'
reportList(mock)
// myMock/reportList.js
/* This file is automatically generated, the modification will not take effect, the modification entry: fe.config.js */
export const init = (mock) = > {
mock.onGet('/getReportList').reply(200, {
data: [{"id":1."reportName":"234"."reportTitle":"33423"."topicIds":"24 31"."status":0."startDate":"2020-11-01"."lateDays":5."createUser":"xxx.li"."updateUser":"xx.li"."createTime":"The 2020-11-18 14:04:17"."updateTime":"The 2020-11-18 14:04:17"},
{"id":2."reportName":"234"."reportTitle":"33423"."topicIds":"24 31"."status":0."startDate":"2020-11-01"."lateDays":5."createUser":"xxx.li"."updateUser":"xx.li"."createTime":"The 2020-11-18 14:04:17"."updateTime":"The 2020-11-18 14:04:17"}].ret: 0.msg: 'ok'
})
mock.onPost('/addReport').reply(200, {
data: [].ret: 0.msg: 'ok'
})
mock.onPost('/updateReport').reply(200, {
data: [].ret: 0.msg: 'ok'
})
mock.onPost('/deleteReports').reply(200, {
data: [].ret: 0.msg: 'ok'})}Copy the code
Code word is not easy, little praise to encourage ~