当我们做项目时,后台开发接口给我们,我们访问一般是跨域访问,那么如何使用 webpack 进行跨域访问,来完成前端测试的接口问题。
我们使用 node 开发后台接口,来模拟这个问题的答案。
const express = require("express");
const app = express();
app.get("/proxy",function(req,res,next){
res.json({"name":"Condor Hero"});
});
app.listen(500);
console.log("500 端口已经成功监听!");
上面的代码使用 node 和 express 配合,来模拟了 http://127.0.0.1:500/proxy 这个接口。
访问结果:
现在的问题是 8080 得不到 500 的数据。要设置代理跨域,改变前端的webpack.config.js:
//webpack.config.js
// var path = require("path");
// 使用webpack-dev-server 就不需要path
module.exports = {
mode:"development",
entry:"./App/main.js",
output:{
// webpack要求的输出路径
// path:path.resolve(__dirname,"dist"),
// webpack-dev-server的虚拟输出路径虚拟生成,不损坏硬盘,效率很高,热更新
publicPath:"virtual",
filename:"all.js"
},
// webpack-dev-server 动态实时更新不在需要watch:true;
// watch:true,
module:{
rules:[
{
test:/\.less$/,
use: [
{
loader: "style-loader" // creates style nodes from JS strings
},
{
loader: "css-loader" // translates CSS into CommonJS
},
{
loader: "less-loader" // compiles Less to CSS
}
//上面的另一种写法
//use: ['style-loader', 'css-loader','less-loader']
]
},
{
test: /\.m?js$/,//匹配.mjs和.js结束的文件
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env','@babel/preset-react'],
// @babel/plugin-proposal-object-rest-spread翻译高级ES的...
// @babel/plugin-transform-runtime翻译高级ES的带星函数即Generator
plugins: ['@babel/plugin-proposal-object-rest-spread','@babel/plugin-transform-runtime']
}
}
}
]
},
resolve: {
//自动解析确定的扩展。默认值为:
extensions: [".js", ".json", ".jsx", ".css"],
//解析目录时要使用的文件名。默认:
mainFiles: ["index","Index"]
},
// 代理跨域
devServer: {
// 此处可以自定义访问端口号
port : 8080,
proxy: {
'/api': {
target: 'http://localhost:500',
// pathRewrite 表示代理路径是否是 URL 的一部分
// 默认不写 pathRewrite,/api 就是 URL 的一部分,开发环境和生产环境都不能去掉
pathRewrite: {'^/api' : ''} // api 只在开发环境下有,不是 URL 的一部分
}
}
}
}
webpack 官网配置地址 :https://webpack.js.org/configuration/dev-server/#devserverproxy
webpack-dev-server 的底层用的是 http-proxy-middleware (React 中用这个 package 也能跨域),http-proxy-middleware 底层用的是 http-proxy。
此时任何 500 的端口,都会被偷到 8080 端口来,但是要补一个 /api
:
以前:
现在:
http://127.0.0.1:8080/api/proxy
成功跨域。
上面是在本机上测试的,但请注意偷取别人的服务器时别忘了的改target
:
target: 'http://localhost:500'变成别的电脑IP
target: 'http://192.168.2.250',
这时我们在引入访问就可以直接/api/proxy
。
另外如果代理地址是 https 的,需要配置:
secure: false
如果代理的主机服务器是虚拟主机,请求接口可能会出现 404 状态码,此时需要改写主机头 origin:
changeOrigin: true
返回 404 的原因是:
如果后端服务托管在虚拟主机的时候,也就是一个IP对应多个域名,需要通过域名区分服务,那么参数
changeOrigin
必须为true(默认为false),这样才会传递给后端正确的Host头,虚拟主机才能正确回应。否则http-proxy-middleware会原封不动将本地HTTP请求发往后端,包括Host: localhost
而不是Host: httpbin.org
,只有正确的Host才能使用虚拟主机,不然会返回404 Not Found。
webpack 代理返回 404,changeOrigin的原理