白嫖即食:构建工具的proxy代理配置区别(解决跨域)

1,048 阅读5分钟

前言

前几天被leader要求在组内分享一下关于这个知识,然后惨兮兮地由原来6点下班逼迫到7点,分享期间leader就在我旁边一直引导,总得来说还算不错,所以也就在这边也进行一个分享啦。

背景

当我们在进行接口联调的时候,需要对相应的接口地址发送请求,但前端和后端的域名是不一样的,所以这个时候就需要进行跨域请求,而对于跨域问题常用的方法就是在构建工具中进行代理。

目前前端开发中常用的构建工具是webpackvite ,用于打包、编译和管理前端项目。今天我主要分享的是它们在配置代理服务器方面的一些不同之处,对于其他的配置就暂且不进行延申。

区别

Webpack 是一种广泛使用的前端构建工具,Webpack 不提供内置的代理功能,但你可以使用 webpack-dev-server 第三方依赖在开发时启动一个开发服务器,并通过配置实现代理。

vite 是新一代的一种前端构建工具,它在开发服务器中提供了内置的代理功能,并且在处理模块时采用了 ES 模块的原生支持,因此其配置和使用方式与传统的 webpack-dev-server 有些不同。

一、Webpack proxyTable

Webpack是通过在 webpack.config.js 配置文件中的 dev 字段下添加proxyTable 选项来实现,并使用pathRewrite来重写路径,这样就可以将开发环境中的请求代理到其他的后端服务器,解决跨域问题。例如:

// webpack.config.js
module.exports = {
  // ...
  dev: {
    proxyTable: {
      '/api': {
        target: 'http://api.example.com', // 后端提供的接口
        changeOrigin: true,  // 是否改变请求头的HOST字段
        pathRewrite: {  // 重写路径,以正则表达式来重写
          '^/api': ''
        }
      }
    }
  }
};

这里的配置意味着将所有以 /api 开头的请求代理到 http://api.example.com,并且会对路径进行重写

二、Vite proxy

Vite 使用不同的方式来配置代理。你可以在 vite.config.js 文件中,使用sever字段下的 proxy 选项来设置代理,并通过rewrite来重写路径。与 webpack-dev-server 的 proxyTable 相比,Vite 的配置方式更加简洁和直观:

// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://api.example.com', // 后端提供的接口
        changeOrigin: true, // 是否改变请求头的HOST字段
        rewrite: path => path.replace(/^/api/, '') // 重写路径,以正则表达式来重写
      }
    }
  }
};

这里的配置与 webpack-dev-server 类似,将以 /api 开头的请求代理到 http://api.example.com,并且同样会对路径进行重写。

主要区别:

  • 配置文件名称:Webpack 使用的是 webpack.config.js,而 Vite 使用的是 vite.config.js
  • 配置项名称:Webpack 使用 dev.proxyTable,Vite 使用 server.proxy
  • 路径重写:Webpack 使用 pathRewrite,Vite 使用 rewrite

三、uniapp Proxy

uni-app 中,uni-app 也内置了代理功能,你可以通过在 manifest.json 文件中的 devServer 配置节点来设置代理。

{
  "devServer": {
    "proxy": {
      "/api": {
        "target": "http://api.example.com",
        "changeOrigin": true,
        "pathRewrite": {
          "^/api": ""
        }
      }
    }
  }
}

总结而言,两者的功能相似,都是为了解决开发环境中的跨域问题,但 Vite 的配置更加简洁并且与其模块化的构建方式更为契合。

食用方法

比如现在后端提供的地址为http://api.example.com,而我前端的地址为http://127.0.0.1:8080,那就必定会遇到所谓的跨域问题 之前我的解决办法是,先配置axios的默认请求域名,axios.defaults.baseURL = '``http://api.example.com``',我使用的是nodejs来搭服务器的,所以配置的 access-controll-allow-orgin: ``http://127.0.0.1:8080来解决跨域

而到了公司这边,使用的确是webpack-dev-serve来进行代理,相关配置放在webpack.config.js或vite.config.js或vue.config.js中,在这里的配置我就说说比较关键一点的,其他的可以去官网看看webpack-dev-server

module.exports = {
  devServer: {
    proxy: {
      '/hls-pc': {
        target: 'http://api.example.com',
        changeOrigin: true,
      },
    },
  },
};

再结合一个axios请求来进行理解

axios.get('/hls-pc/getUserInfo') 
    .then(response => { console.log(response.data); }) 
    .catch(error => { console.error(error); });

当你在前端发送一个axios请求时,你实际的请求地址是http://127.0.0.1:8080/hls-pc/getUserInfo来进行请求,但这明显是不对的,所以在dev-serer配置中,我们将以 /hls-pc开头的请求代理到target: http://api.example.com上,即把http://127.0.0.1:8080/hls-pc/getUserInfo替换(代理)成http://api.example.com/hls-pc/getUserInfo,也就是把前端主机请求地址中 /hls-pc之前的全部代理成target指向的地址

不过,真正发送请求还得加上changeOrigin: true,它改变的是请求头上Host字段,

  1. 如果没有使用 changeOrigin,代理服务器会将该请求直接转发到后端 API,但是请求头中的 Host 字段仍然为 127.0.0.1:8080。后端服务器接收到请求后,会检查请求头中的 Host 字段,发现该域名为 127.0.0.1:8080,而不是它预期的后端域名 api.example.com
  2. 后端服务器可能会认为这个请求来自一个未授权的域名,出于安全原因,它可能会拒绝这个请求,或者执行一些其他的安全策略。
  3. 结果就是,前端请求没有正确代理到后端 API,可能会收到跨域错误或拒绝访问等问题。

通过设置 changeOrigin: true,代理服务器会修改请求头中的 Host 字段,将其改为后端 API 的域名 api.example.com,这样后端服务器就会正确识别请求的来源,并且能够正常处理请求。

讲了这么多targetchangOrigin的配置,基本也算掌握了webpack-dev-server的用法了,然后就是不怎么用的pathRewrite,用法和它的意思一样,重写路径,

module.exports = {
  devServer: {
    proxy: {
     '/hls-pc/getUserInfo': {
        target: 'http://api.example.com',
        changeOrigin: true,
        pathRewrite: {
          '^/hls-pc': '',
        },
      },
   }
}

也就是当你如果不希望传递/hls-pc的时候,则需要重写路径:最后实际请求路径为'``http://api.example.com/getUserInfo',也就是按照配置'^/hls-pc': '',匹配到 /hls-pc的为空

整体代码为

module.exports = {
  devServer: {
    proxy: {
     '/hls-pc/getUserInfo': {
        target: 'http://api.example.com',
        changeOrigin: true,
        pathRewrite: {
          '^/hls-pc': '',
        },
      },
       '/hls-pc': {
        target: 'http://api.example.com',
        changeOrigin: true,
      },
   }
}

注意,配置的执行顺序是从上到下依次执行的,所以先请求的放到最上面,并且每个配置的target可以指向不同的后端接口地址,相比于access-controll-allow更加的灵活,更适合用于前端开发环境