在构建公司项目的时候遇到了这样一个问题公司的项目上线之前需要经过测试。这是每个公司都会有的流程。就比如我们公司,项目发布之前要先经过测试环境测试和预发环境测试最后才是生产环境。

环境变量

那么问题就来了,这么多环境每个环境的后台服务器地址是不样的,总不能每发布一个环境就改一次代码吧。

于是就有了环境变量,根据环境变量判断当前所需要部署的环境,输出对应的服务器地址。那么我们该如何设置环境变量呢?我使用的是cross-env能跨平台设置和使用环境变量的脚本。

cross-env 的安装使用

安装
npm install --save cross-env
复制代码
配置
  1. 打开Vue项目根目录下package.json修改scriptsbuild命令,这里我们将环境变量process.env.ENV设置为dev(ps:如果有多个环境则需要添加)
"build:dev": "cross-env ENV=dev node build/build.js",
复制代码
  1. 修改build/webpack.prod.conf.jswebpack.DefinePlugin的配置。我们看webpack.DefinePlugin原来的配置代码。可以看到他的配置来自变量env。所以我们只需要更改变量env的值就可以了。所以我们增加代码 env.ENV= `"${process.env.ENV}"`;
const env = process.env.NODE_ENV === 'testing'
     ? require('../config/test.env')
     : require('../config/prod.env')
     env.ENV= `"${process.env.ENV}"`; //我们增加的代码
     
     //这里我们省略无关的代码只看关键部分
     
    new webpack.DefinePlugin({
      'process.env': env //来自上面定义的变量env
    })
复制代码
  1. 修改build/build.js(为了build时输出正确的提示信息)
// const spinner = ora('building for production...') //修改前
const spinner = ora(`building for ${process.env.ENV}...`)//修改后
复制代码
  1. 完成以上步骤之后我们就可以在代码中通过process.env.ENV获取我们定义的环境变量了。

服务器地址及接口信息配置

配置文件目录结构
vue/
└── src/                                  项目目录(alias:@)
    └── server/                           服务器地址及接口配置目录
        ├── api/                          接口目录
        ├── config/                       服务器地址配置目录
        ├── utils/                        工具类
        └── index.js                      暴露接口信息
复制代码
目录 utils/
在目录utils/下新建convertUri.js
var api = {}
/**
 * 根据环境变量引入相应的服务器配置文件
 */
console.log('process.env.ENV', process.env.ENV)
if (process.env.ENV === 'prod') {
  api = require('../config/api.prod').default
} else {
  api = require('../config/api.dev').default
}
/**
 * uri转url
 */
export default (url) => {
  for (const key in api) {
    const reg = new RegExp(`^/?:${key}`)
    if (reg.test(url)) {
      return url.replace(reg, api[key])
    }
  }
  return url
}

复制代码
在目录utils/下新建oauthJudge.js(ps:这是用于部分接口请求头不需要携带token的判断,若你的项目中不需要类似 oauth2.0 权限验证则不需要新建该文件)
/** 不需要 Authorization 的接口列表 */
const apiList = [
  /user\/token/,
  /user\/register/,
  /user\/check_username/,
  /captcha/,
  /article\/get/,
  /sort\/get/,
  /label\/get/
]
/** 判断是否需要携带 token */
export default url => {
  return apiList.every(item => {
    return !item.test(url)
  })
}
复制代码
在目录utils/下新建request.js
import axios from 'axios'
import convertUri from './convertUri'//服务器地址配置,及URI与URL之间的转换
// import { Notification } from 'element-ui'//这是element-ui的通知的方法如果有需要可以安装element-ui后调用
// import store from '@/store'//引入vuex,按需引入
// import router from '@/router'//引入vue-router,按需引入
// import oauthJudge from './oauthJudge'//判断接口是否需要权限验证的方法,按需引入
// 创建axios实例
const service = axios.create({
  timeout: 60000 // 请求超时时间
})

// request拦截器
service.interceptors.request.use(
  config => {
    // URI与URL之间的转换
    config.url = convertUri(config.url)
    // let token = store.getters.token || null 从vuex获取token请根据实际情况自行修改
    // 请求头带token
    // if (token && oauthJudge()) { //判断token是否存在 与 接口是否需要权限验证
    //   config.headers['Authorization'] = 'Bearer ' + token // 让每个请求携带自定义token 请根据实际情况自行修改
    // }
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// respone拦截器
service.interceptors.response.use(
  response => {
    /**
     * code为非200是抛错 可结合自己业务进行修改
     */
    const res = response.data
    if (response.status !== 200) {
      return Promise.reject(res)
    } else {
      return response.data.data
    }
  },
  /**
   * 响应出错的处理
   */
  error => {
    return Promise.reject(error)
  }
)
export default service
复制代码
目录 config/
新建文件api.dev.jsapi.prod.js文件格式如下
const url = 'http://localhost:3000' //Base_URL

// 服务器链接配置建议按模块划分
export default {
  // 用户管理模块
  user: `${url}/user`,
  // 验证码模块
  captcha: `${url}/captcha`,
  // 标签模块
  label: `${url}/label`,
  // 分类模块
  sort: `${url}/sort`,
  // 评论模块
  comment: `${url}/comment`,
  // 博文模块
  article: `${url}/article`
}
复制代码
目录 api/
建议的文件目录结构按接口模块划分比如:
api/
├── user-controller/                        用户管理模块
├── label-controller/                       标签管理模块
├── comment-controller/                     评论管理模块
├── captcha-controller/                     验证码管理模块
├── article-controller/                     文章管理模块
└── sort-controller/                        分类管理模块
复制代码
user-controller/目录下新建login.jsindex.js
//login.js
import request from '@/server/utils/request'
/**
 * 登陆 获取token
 * @param userName 用户名
 * @param userPassword 用户密码
 */
export default (userName, userPassword) => {
  return request({
    url: '/:user/token',
    method: 'post',
    data: { user_name: userName, user_password: userPassword }
  })
}
复制代码
//index.js
import login from './login'
/**
 * 用户管理模块接口方法的集合
 */
export default {
  login
}
复制代码
暴露接口信息 index.js
import articleController from './api/article-controller'
import captchaController from './api/captcha-controller'
import commentController from './api/comment-controller'
import labelController from './api/label-controller'
import sortController from './api/sort-controller'
import userController from './api/user-controller'

export default {
  ...articleController,
  ...captchaController,
  ...commentController,
  ...labelController,
  ...sortController,
  ...userController
}

复制代码

Vue中的调用

通过上述方法我们将所有的接口方法都定义在了目录server/api/中那么我们该如何调用呢?

main.js引入

main.js中增加下面两条代码

import api from '@/server'
Vue.prototype.$api = api
复制代码

那么我们就可以直接在Vue组件中通过this.$api.login()调用login方法访问接口了。

最后如何build

npm run build:dev
复制代码