配置vite代理和区分测试/生产环境,封装axios接口请求

5,462 阅读2分钟

分享一下axios baseURL 的配置和接口请求的封装。

优势主要有以下几点

  1. 支持自动切换测试和生产环境,支持手动切换本地环境;
  2. 划分好所有接口 api 地址,封装所有 api 请求的方法,更方便在项目中添加接口;
  3. 如果接口超时可以全局捕获,统一处理;

一、配置 vue.config.js 文件

有时候我们需要获取测试环境的数据,有时候则需要生产环境的数据,那么一次性配置好代理方式,就不用反复重启我们的本地服务了。

/vue.config.js

module.exports = {
  devServer: {
    proxy: {
      '^/dev2test': {
        target: 'https://api.test.cn', // 测试
        changeOrigin: true,
        pathRewrite: {
          '^/dev2test': '/specific-test',
        },
      },
      '/dev2production': {
        target: 'https://api.prod.cn', // 生产
        changeOrigin: true,
        pathRewrite: {
          '^/dev2production': '/',
        },
      },
    },
  },
};

二、添加对接口 baseUrl 判断的变量

通过 process.env.NODE_ENV 判断开发环境和非开发环境,如果是非开发环境还可以通过部署域名window.location.hostname来判断环境,使得测试环境代码和生产环境请求代码是同步的,不用每次上生产还要注释或者修改 baseUrl 内容,减少了人工操作失误带来的损失。

/src/api/environment.js

/**
 * 判断环境返回响应的接口前缀
 */

export const URL_PREFIX = {
  // 开发环境接口代理 0:测试;1:生产
  DEV: ['/dev2test', '/dev2production'][0],
  // 测试环境接口基础url
  TEST: '/specific-test',
  // 生产环境基础基础url
  PROD: '/',
};

export const isDevelopEnv = process.env.NODE_ENV === 'development'; // 是否为开发环境
export const isTestEnv = window.location.hostname === 'api.test.cn'; // 是否为测试环境

/* 接口地址 */
export const customBaseUrl = isDevelopEnv
  ? URL_PREFIX.DEV
  : isTestEnv
  ? URL_PREFIX.TEST
  : URL_PREFIX.PROD;

三、创建axios实例和封装请求方法,添加超时拦截

将我们的接口路径统一划分到一个文件夹,使用一个对象表进行记录,除了支持 path 属性,还可以根据业务添加请求方法 method 或者是否鉴权等信息。

/src/api/urlList.js

/* 接口路径列表 */
export const apiList = {
  login: { path: `/box/login/url` },
  getToken: { path: `/box/getToken` },
};

将上面的接口路径分别封装成功一个 axios 请求,同时暴露出一个对象,该对象拥有所有多个 promise 请求,方便在业务中使用或者直接注册到Vue根实例上。同时还可以在响应拦截中,捕获超时的错误信息,进行请求超时提示。

/src/api/index.js

import axios from 'axios';
import { customBaseUrl } from './environment';
import { apiList } from './urlList';

/* 初始化axioas */
let service = axios.create({
  baseURL: customBaseUrl,
  timeout: 20000,
});

/* 封装接口请求 */
const methods = Object.keys(apiList).reduce((acc, cur) => {
  let { path, method = 'get' } = apiList[cur];
  const promise = async (params) => {
    const key = method === 'get' ? 'params' : 'data';
    let config = {
      method,
      [key]: params,
    };
    let { data } = await service(path, config);
    return data;
  };
  // 确保返回的均为promise
  return Object.assign(acc, {
    [cur]: promise,
  });
}, {});

/* 响应拦截 */
service.interceptors.response.use(
  (response) => response,
  (error) => {
    // 拦截接口超时
    const isTimeOut =
      error.code == 'ECONNABORTED' && error.message.indexOf('timeout') !== -1;
    if (isTimeOut) {
      const Toast = undefined; // 可引入vant的Toast组件
      Toast && Toast.clear();
      Toast && Toast.fail('网络繁忙,请稍后重试');
    }
    // 处理响应失败
    return Promise.reject(error);
  }
);
export default methods;

四、 基本使用

直接通过 import 导入就可以使用了,如果有需要还可以全局注册到 Vue 实例上。

/src/App.vue

import apis from './api/index';
export default {
  name: 'App',
  components: {
  },
  created() {
      apis.login();
  }
}