写在前面
小编在开发过程中从原生的jq+css写代码,到vue-cli脚手架搭建项目,都遇到了跨域问题,之前解决跨域问题一般都是后台加请求头,前端用jsonp的话只适用于get请求,也是很少用,自从node.js npm 模块的出现,也就出现了前端使用代理解决跨域使用http-proxy-middleware 代理解决,下边说一下具体的解决办法。
使用http-proxy-middleware 代理解决(项目使用vue-cli脚手架搭建)
首先需要先安装
npm install --save-dev http-proxy-middleware
网上有一大堆关于这个插件的原理,请自行google,这里就不详细解释,这是写出来自己的理解。
proxy中间件配置
proxy([context,] config)
var proxy = require('http-proxy-middleware'); //引入插件
var apiProxy = proxy('/api', {target: 'http://www.example.org'});
// \____/ \_____________________________/
// | |
// 需要转发的请求 目标服务器
// 'apiProxy' 现在已经准备作为一个中间件了。
只看这个只是知道了他的原理是通过代理将请求代理到你想请求的服务器上,然而还不知道怎么用?
在vue-cli项目中的config文件夹下的index.js配置文件中,在proxyTable中添写如下代码
加入服务器提供的接口如果长这样https://www.exaple.com/server_new/login,我们把域名提取出来如https://www.exaple.com;
//在开发下边配置
dev: {
env: require('./dev.env'),
port: 9521,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
*********** //http-proxy-middleware 解决跨域的配置
proxyTable: {
'/api': {
//将www.exaple.com映射为/apis
target: 'https://www.exaple.com', // 接口域名,被请求的地址
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, //是否跨域
pathRewrite: {
'^/api': '/api' //需要rewrite的,
}
}
},
cssSourceMap: false
}
也就是用
/api
代理了https://www.exaple.com这个域名。
如上所述,跨域的代理配置就好了,小编在项目中使用的是axios请求,所以在开发中就是这样了
var url = '/server_new/login'; // 这里就是刚才的config/index.js中的/api,由于你在重写的方法里边哦配置了`/api`所以就不用每个接口都写了。
//此时需要把dataUrl挂在到vue实例上.
this.$axios
.get(this.dataUrl + url)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
这样是解决跨域问题了,但是打包部署是就会出问题。
所以我就在confing配置了一下,由于项目封装的比较多,用的axios拦截器,所以需要配置多个,
一,先说个最简单的办法就是:
配置一个开发时的路径,配置一个上线的路径
let serverUrl = '/api/' //本地调试时
// let serverUrl = 'https://www.exaple.com' //打包部署上线时
export default {
dataUrl: serverUrl
}
接下来再看看我自己的项目中的配置。
首先在config目录下有三个文件,分别是index.js,基本配置,dev开发环境的配置,prod生产的配置,这样就可以一劳永逸了。
- index.js
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 9521,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
//http-proxy-middleware 解决跨域的配置
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}
- dev.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '"/"', //开发环境的接口地址,api在连接跨域时已经配置好了,所以这里只需要写个/就好了
});
- prod.env.js
module.exports = {
NODE_ENV: '"production"',
BASE_API: '"http://testpvt.boss.pb-raising.com/pbs"', //这个是线上的环境接口
}
上边的配置好了后,然后再axios的全局拦截器中配置好请求
import axios from 'axios'
// 创建axios实例
// https://www.kancloud.cn/yunye/axios/234845
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 100000, // 请求超时时间
// 所有请求都以Json形式传送
// 会有预检请求,服务端需要正常通过OPTIONS请求
// http://www.ruanyifeng.com/blog/2016/04/cors
headers: {
// 'Content-type': 'application/json;charset=UTF-8',
//'Content-type': ['application/json;charset=UTF-8', 'application/x-www-form-urlencoded'],
//'Access-Control-Allow-Origin': '*',
//'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
//'Access-Control-Allow-Methods': '*'
}
});
// request拦截器 请求
service.interceptors.request.use(config => {
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
})
// request拦截器 响应
service.interceptors.response.use(config => {
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
})
export default service
结束语
至此,vue-cli的跨域问题就解决了,还有什么写的不清楚的地方,还请简友多多指教。