今天本地开发一个新项目的时候,遇到了一点问题:项目本地启动之后的localhost页面,请求服务端接口,报跨域错误。
搜索了一下,这个问题网上的解决办法已经很明确了:配置webpack proxy
,在webpack配置文件中添加以下配置即可:
{
devServer: {
proxy: {
"/api": {
target: "htttp://www.expample.com/",
changeOrigin: true
}
}
}
}
这样本地启动之后,再请求就不会报跨域错误了。
但是,因为我们起码有两个环境:测试环境和生产环境,经常需要代理到不同环境的服务。
如果使用以上配置,需要经常修改devServer.proxy.target
配置的值,这有点麻烦。那能不能在启动项目时通过命令行参数指定想要代理到的服务呢? 比如这样:
npm run dev --devproxy=http://www.example.com/
Step 1
首先,需要把devproxy
参数设置到node的环境变量中,$npm_config_devproxy
会读取到我们在命令行参数中传递的devproxy
的值,随后我们把它赋给DEVPROXY
环境变量。
这样,后续我们就可以在webpack配置文件中通过process.env.DEVPROXY
读取devproxy
参数的值了。
此外,为了跨平台的兼容性考虑,最好加上cross-env。
//之前的dev命令
{
"scripts": {
"dev": "nfes-nmf start",
}
}
//在dev命令中设置devproxy参数到node的环境变量
{
"scripts": {
"dev": "cross-env DEVPROXY=$npm_config_devproxy nfes-nmf start",
}
}
Step 2
在webpack配置文件中读取devproxy
参数。并用于配置devServer.proxy.target
。
{
devServer: {
proxy: {
"/api": {
target: process.env.DEVPROXY,
changeOrigin: true
}
}
}
}
Step 3
到这里,已经可以通过--devproxy=
来配置webpack代理。我们最后再做一点锦上添花的小工作:在配置代理、启动项目之后,我们有时候想知道现在是代理到了哪个服务端环境? 最终实际请求的url是什么样的?
所以我们可以在每个请求的响应头 (Response Headers
) 加上一个X-Real-Url
字段,表示这个请求实际的url。
添加配置项onProxyRes
:
{
devServer: {
proxy: {
"/api": {
target: process.env.DEVPROXY,
changeOrigin: true,
onProxyRes: function (proxyRes, req) {
proxyRes.headers["X-Real-Url"] = `${process.env.DEVPROXY}${req.url}`;
},
}
}
}
}
效果请看下图,在Devtool Network
找到某一个被代理的请求:
至此,就完成了所有的配置~
Q&A
做这个配置期间,遇到一点小问题:process.argv
可以直接读取到命令行传入的参数,那么为什么我们这里还要用process.env
呢?
因为我的npm scripts
里,dev
命令是这样的:
{
"scripts": {
"dev": "nfes-nmf start",
}
}
实际运行的是一个第三方包的命令,它没有直接运行webpack配置文件,所以等到运行项目内的webpack配置文件时,读取process.argv
得到的只有:
["node", "运行的js文件路径", "start"]
拿不到devproxy
的值,所以我选择了用 赋值环境变量、再读取的方式来代替process.argv
。