Vue项目运用webpack多环境配置的问题和本地开发跨域问题

实际运用场景

在我们开发前端应用中,往往需要使用多个环境,例如

1.本地开发环境

2.测试环境

3.正式环境

所以每个环境都需要对相应的服务器地址、环境专属变量等做出单独的配置。

Vue项目

1.初始化

我们使用vue-cli init生成的项目,调试与打包已经为我们在package.json中做好了

/* /package.json */
"scripts": {
    "dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run e2e",
    "build": "node build/build.js",
  }

* 之前遇到的问题:本地调试 localhost:8080 可正常访问,但是使用本机ip(http://192.168.*.*:8080)无法访问;

解决方法:在package.jsondev命令加上 0.0.0.0

* 这里想特别说明一下的是,vue-cli脚手架帮我们生成好了整个项目,而且也有对应webpack.dev.conf.jswebpack.prod.conf.js两个分离的webpack配置文件,但由于文件的命名问题(dev.conf.js/prod.conf.js),很容易让人误以为这两个文件就是webpack针对不同环境的配置。但实际上这两个文件一个是用于本地调试时的配置文件,另一个是用于打包部署的配置文件。调试/打包两种模式 与 环境(dev/test/pre/prod等)是可以相互组合的。理论上来讲这两个webpack的配置文件我觉得应该叫webpack.debug.conf.jswebpack.build.conf.js会更贴切一点。

2.环境参数传递

通过yargs可以方便的获取指定名称的命令行参数,它是node.js中的一个组件,可以通过npm直接安装。

$ npm install yargs --dev --save

/* hello.js */
const argv = require('yargs').argv;
console.log('hello ', argv.env);

/* 命令行 */
$ node ./hello.js --env test
hello test

接下来就要看看如何利用这个参数实现多文件配置。

3.引入环境参数

Webpack中可以使用DefinePlugin插件来配置我们的环境

/* /build/webpack.dev.conf.js: */
plugins: [
    new webpack.DefinePlugin({
      // 源码中所有 process.env 都会被替换为
      // '../config/dev.env'这个module export出来的东西
      'process.env': require('../config/dev.env')
    })
]

/* /config/dev.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

我们可以通过上面传入到脚本中的环境参数,动态加载不同环境的配置文件,以达到切换环境的目的。动态加载不同配置环境的代码:(/build下新建webpack.env.conf.js

/* /build/webpack.env.conf.js */
// 定义参数配置
const argv = require('yargs').argv;

// 获取环境变量
const env = argv.env;
process.stdout.write('the env is '+ env +'\n');

// require指定的环境配置文件
const envConfigFile = "../config/" + env + ".env.js";
process.stdout.write('the env config file is '+ envConfigFile +'\n');

// 将require的配置文件原封不动export回出去
module.exports = require(envConfigFile);

接下来要将动态加载的环境文件丢到webpack的配置文件中,由于webpack.dev.conf.jswebpack.prod.conf.js都是继承自webpack.base.conf.js,所以我们直接改写wepack.base.conf.js的插件配置部分,直接添加DefinePlugin插件的配置,并去掉原配置文件该插件的配置:

/* /build/webpack.base.conf.js */

// 引入上面的webpack.env.conf模块
const envConfig = require('./webpack.env.conf')
module.exports = {
  ...
  ,
  // 配置DefinePlugin插件
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': envConfig
    })
  ],
  ...
}

然后调试/打包的命令我们可以这样写:

/*/package.json*/

"scripts": {
    "dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run e2e",
    "build": "node build/build.js",
    "start:dev": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env dev",
    "start:test": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env test",
    "start:prod": "webpack-dev-server --inline --host 0.0.0.0 --progress --config build/webpack.dev.conf.js --env prod",
    "build:dev": "node build/build.js --env dev",
    "build:test": "node build/build.js --env test",
    "build:prod": "node build/build.js --env prod"
  },

几个环境配置的内容:

/* /config/test.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
  NODE_ENV: '"testing"',
  API_HOST:'"http://*.*.*.*:8580/"' //测试环境
})

/* /config/prod.env.js */
'use strict'
module.exports = {
  NODE_ENV: '"production"',
  API_HOST:'"http://*.*.*.*:8580/"'  //生产环境
}

/* /config/dev.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  API_HOST: '"/api"'  //开发环境
})

* 这里dev环境配置里的API_HOST为什么要写成 '"/api"',我们等下说到跨域再讲。

这样我们就可以通过process.env.NODE_ENV来获取各个环境的参数值(dev/test/prod)

在api模块中可以这样写:

/* /src/api/index.js */
const API_HOST = process.env.API_HOST;

export default API_HOST

然后,在我们的Vue组件中就可以很方便的使用这些环境配置了:

/* /src/components/HelloWorld.vue */

import api_host from '@/api'
data () {
    return {
      msg: 'Welcome',
      env: process.env.NODE_ENV,
      api_host: api_host,
    }
}

最后,使用各自命令打包发布各个环境:

# serve with hot reload at localhost:8080
npm run start:dev
npm run start:test
npm run start:prod

# 发布测试环境:
npm run build:test
# 发布正式环境:
npm run build:prod

# 设置API_HOST, PATH: ./config/*.env.js
API_HOST:'"http://*.*.*.*:8580/"'

4.本地调试跨域

我们在本地开发调试后台给的接口(后台未配置跨域)时,不同ip之间的访问,往往有跨域问题。

Vue-cli 创建的项目,可以直接利用 Node.js 代理服务器,通过修改vue proxyTable接口实现跨域请求。

在vue-cli项目中的config文件夹下的index.js配置文件中,修改当前的dev

/* /config/index.js */
  dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': { //代理地址(适用于开发环境)
        target: 'http://10.10.*.*:8580',//设置你调用的接口域名 别忘了加http
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api': '/'//这里理解成用‘/api’代替target里面的地址,后面组件中我们调接口时直接用api代替 比如我要调用'http://10.10.*.*:8580/rank/info/?rankid=23784&page=1&json=true',直接写‘/api/rank/info/?rankid=23784&page=1&json=true’即可
        }
      }
    },
}

前文提到dev环境配置里的API_HOST为什么要写成 '"/api"',就在于此,改成代理地址即可跨域访问接口

/* /src/api/api.js */

import axios from 'axios'
import urls from './url'
import api_host from '@/api'

// 定义axios基本设置
const request = axios.create({
  baseURL: api_host
})

export default () => {
  return {
    async getData (obj) {
      return handleRequest(await request.post(urls.testUrl, obj))
    },
    async getJSON(){
      return handleRequest(await request.get(urls.testJson, {}))
    }
  }
}

参考博文:Webpack下多环境配置的思路、vue-cli项目开发/生产环境代理实现跨域请求+webpack配置开发/生产环境的接口地址

 

你可能感兴趣的:(前端)