前端篇论管理后端接口的最终方案

4,352 阅读2分钟

背景

前端的一生,离不开三件事,兼容,ui与后端接口

在刚开始工作没多久的时候,看着后端提供的那串玩意就在想,应该怎么样才能优雅的处理这几串东西。在工作的转场中,我试图从别人身上去寻找那份答案,但终究都不是我想要的那份真物。

阶段

在学习的路上,接触了几种方式

各自为政

刚刚开始碰到的是游击战模式,接口路径,他在这头,她又在另外一头,有时候他在这头,他还在另外一头。

this.$fetch('api/commodity')
function login () {
---
---
fetch('api/login')
---
---
}

只把一些诸如登陆、用户信息等全局接口进行封装,没有一个明确的get模块和set操作分离,去对应后端的接口文档,在团队开发的时候,会带来一定程度的混乱。

中央集权失败

第二份工作时,在项目结构中看到了一个api.js,里面记录了一些后端接口的路径,在使用的时候,直接引用这个文件。

src/api
epxort default {
	LOGIN: 'api/login',
    GET_USER_INFO: 'api/userInfo',
}
// src/App.vue
this.$fetch(this.$api.LOGIN)

初用没什么毛病,但是后面碰到了'api/commodity/:id'这种params的路径,就无从下手了,终究还是伪物,变回各自为政。

进厂

再后来,写后台管理时,看到了一整个api目录,打开一看,一堆堆结构一样的函数正在出厂

export function login () {
	return fetch('api/login')
}
export function userInfo () {
	return fetch('api/userInfo')
}
export function getCommodityDetail (id) {
	return fetch('api/commodity/' + id)
}

终于有一个有模有样的get模块了,用的时候,只需import { login } from 'src/api'引入,来源明确并可复用。

但是,随之带来大量的冗余,对于程序员来说,怎么能忍。在可读性不降低的情况下,能少一个字符,绝不加多一个字符

生产力

一个个无产阶级拿起了锄头和镰刀,创造了各种工厂函数,通过简单的数据结构批量生产出接口函数,从手动挡进化成自动挡,大大减少了重复劳动力。这里我推下我的解决方案box-cat。更具体可以看强行震惊!竟然解决了请求接口中的冗余

import { createApis, createProxy } from 'box-cat'
import response from 'src/response' // response可以是axios、flyio.js之类的http请求库
import data from 'src/data'
const api = createApis(data, response)
const apiProxy = createProxy(data, response)

有两种模式,前者是普通,后者是proxy,按需生成接口函数,碰到兼容,会优雅降级到createApis。

工程化

工厂带来的是整个export default导出,虽然有proxy模式,但是与进厂那段,缺少了export的按需引入,来源明确这两个特点。为了补充这两个特点,我们总不能将出厂的产品每一个都手动export出去吧,那不就脱裤子放屁,而且还low。

在观看了一些ast的操作后,决定去写一个loader去解决这个问题。然后开始跌跌撞撞,手忙脚乱的弄完了人生第一个loader——box-cat-loader

目录结构

建议的目录结构,如果项目不大,可以直接一个api/index.js写完

├── response.js // http请求库
├── api
|   ├── module // 各模块的接口路径
|   ├── index.js // 调用box-cat

box-cat-loader会更加数据和产品的变量名进行编译时的自动export。

// src/api/module/index.js
export default {
    getUserInfo: 'api/userInfo',
    getCommodityDetail: 'api/commodity/:id
}
// src/api/index.js
import { createApis } from 'box-cat'
import response from 'test/response'
import data from './module'
const http = createProxy(data, response)
export default http
// box-cat-loader
export const getUserInfo = http.getUserInfo
export const getCommodityDetail = http.getCommodityDetail

loader使用

npm i box-cat-loader -D
// 例子
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, 你的路径 ,'api/index.js') // 指定对该目录进行自动export操作
        ],
        use: {
          loader: 'box-cat-loader',
          options: { // 默认的options如下
            data: 'data', // 数据变量名
            http: 'http' // 产品变量名
          }
        }
      }
    ]
  },
}

在使用的时候,如果喜欢整个导出的话,可以直接使用createProxy,而无需配置loader。看各人喜欢。

这个不止是配合box-cat的,一些同类型的数据结构工厂也可以使用,数据 + 工厂 = 产品。然后通过loader来进行编译时export

规范

// 数据导出只支持export default{}
// 在api的index.js中数据引入可以是:
import data from 'src/api/module'
// 也可以是
import order from 'src/api/module/order'
import commodity from 'src/api/module/commodity'
const data = {
	...order,
    ...commodity,
}

之所以要有这种格式,是因为如果你给我来个data.getUserInfo = 'api/getUserInfo',我这样用ast去找的话,会累死我个人,所以才有出现这种规范,而且按写过的项目来说,目前看来是足够的

结语

本文是抛砖引玉,希望可以看到更多方案讨论。因为是第一次写loader,难免会有很多东西忽视,有大伙可以指点的话,那就更加最好不过了。

一如既往,继续寻找内心的那份真物