在开发的时候,如果我们需要从子域名或者其他网站获得数据接口,可能会碰到跨域问题,这个时候常用的做法是修改hosts文件,或者配置一个反向代理服务器,难免有些麻烦,而且有时候需要测试的接口是开发环境的,就更加繁琐了。本来想用webpack-dev-server的反向代理来实现,发现他的实现方式是http-proxy-middleware中间件,只能反代path即相对路径
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
所以探索了一下,在尽量不干扰源码和生产环境的情况下,便捷的实现测试环境跨域接口的通用解决方案。
本文介绍两种方式,通过简单的修改配置文件和源码,实现用webpack-dev-server来实现接口的反向代理,同时不影响生产环境的打包结果。
两种方式都是一个原理:
- 通过
plugin或者loader来替换所有其他域名接口的scheme+authority为一个不重复的相对路径前缀,本文是unique_dev_server - 让
webpack-dev-server反向代理这些相对路径。
第一种:通过definePlugin
这种方案需要修改源码,如果无法接受看第二种方案
先介绍第一步的配置。
// webpack.prod.js
plugins: [
...,
new webpack.DefinePlugin({
USER_SERVER: JSON.stringify('https://user.domain.com/')
})
]
// webpack.dev.js
plugins: [
...,
new webpack.DefinePlugin({
//unique_dev_server随便写,只要是唯一且不冲突的
USER_SERVER: JSON.stringify('/unique_dev_server/')
})
]
这里开发环境要配置一个path前缀,要确保这个值是唯一的且和本域名的接口不冲突。
同时,配置好这个之后,要在对应的所有调用跨域名接口的js中修改url
/* global USER_SERVER */
fetch(USER_SERVER+"/api/test").then((res) => {
// fetch("https://user.doamin.com/api/test").then((res) => {
改成全局变量,如果你用了eslint,这里要加上global变量的注释。
- 第二步,针对
/unique_dev_server这个url添加反向代理配置
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 9000,
proxy: {
'/unique_dev_server/': {
target: 'http://localhost:8088/',
pathRewrite: {'^/unique_dev_server/': ''},
headers: {
'referer': 'http://domain.com/'
}
}
}
},
重点是target要改成对应域名网址,还有pathRewrite要把前面的key去掉。
如果你的跨域名接口还对referer或者其他header有要求,还可以在这里添加。
完成这两步就大功告成了,如果你还有其他域名接口,只需要在defineplugin和proxy里增加对应的域名即可。
第二种通过string-replace-loader
还有一种不会对源代码产生影响的方式,就是通过string-replace-loader来实现第一步的替换
首先要安装这个loader
npm i string-replace-loader -D
然后修改开发环境webpack配置
// webpack.dev.js
rules: [
{
test: /\.js$/,
loader: 'string-replace-loader',
options: {
search: 'https://dev.example.com/',
replace: '/unique_dev_server/'
}
}
]
proxy的配置看第一种方案的第二步。
这种方式的优点是不会对源代码产生修改,缺点是
- test文件过多,可能会影响编译速度
- 无法处理拼接url的情况(一般也不会有人拼接域名)
- 极低概率会误replace
如果你不想对源码产生影响,且可以接受以上缺点,建议你使用loader方案。