Vue代理详解

发布时间:2023-05-20

一、Vue代理配置

Vue代理是通过配置Vue的webpack来实现的,我们需要在项目目录中找到.env文件,在其中添加如下代码:

// .env
module.exports = {
  devServer: {
    proxy: 'http://localhost:3000'
  }
}

这个简单的配置告诉Vue开发服务器将所有指向/api的请求转发到http://localhost:3000上,这里的/api是为了处理我们请求的API地址中划分出来的命名空间。

二、Vue配置代理

我们需要在Vue实例中添加配置项:

// main.js
import axios from 'axios'
import Vue from 'vue'
Vue.config.productionTip = false
Vue.prototype.$http = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json'
  }
})

这里我们使用了axios来跟后台服务器交互,通过配置baseURL,设置了API请求的基础路径,这里我们可以利用.env中的VUE_APP_BASE_URL变量,方便地切换不同的请求地址。

三、Vue代理事件

利用Vue提供的钩子函数,我们可以在请求发生前和响应返回后对请求进行拦截和处理:

Vue.prototype.$http.interceptors.request.use(config => {
  // 在发送请求之前做些什么
  return config;
}, error => {
  // 对请求错误做些什么
  return Promise.reject(error);
});
Vue.prototype.$http.interceptors.response.use(response => {
  // 对响应数据做些事情
  return response;
}, error => {
  // 对响应错误做些事情
  return Promise.reject(error);
});

四、Vue代理解决跨域

Vue代理最常用的功能就是解决跨域问题,在开发环境中,我们通常会把API接口和Vue程序部署在不同的服务器上,这时候就会存在跨域请求的情况。这时候,我们可以通过Vue代理来将API请求路由到本地服务器上:

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
      }
    }
  }
}

这里我们设置了代理路径为/api,并且将所有指向该路径的请求转发到http://localhost:3000上,changeOrigin选项表示是否将请求的源地址修改为代理服务器的地址。

五、Vue代理原理

Vue代理本质上是一个中间件,当我们发送API请求时,它会进行拦截和处理,将请求转发到指定的API服务器上。这里我们使用的是webpack-dev-server提供的中间件,它的作用是将我们的Vue应用部署到本地服务器上,并提供实时的热更新功能,这样我们就可以进行开发和调试而不必每次都重新打包和上传整个应用程序。

六、Vue代理服务器

Vue代理服务器可以理解为我们的中间件,它是负责处理API请求的主要组件。我们可以在vue.config.js文件中配置不同的代理规则:

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

这里添加了pathRewrite选项,用于将所有API请求的前缀/api替换为空字符串,这样我们就可以直接通过相对路径来发送请求了。

七、Vue代理加载过程

Vue代理加载过程通常是由Webpack和webpack-dev-server进行自动化配置的,其主要步骤如下:

  1. 设置代理路径和目标地址
    我们需要在.envvue.config.js文件中设置代理规则,指定代理路径和代理目标,例如:
    // .env
    module.exports = {
      devServer: {
        proxy: 'http://localhost:3000'
      }
    }
    
  2. 自动识别被代理的API请求
    webpack-dev-server会自动匹配所有的API请求,并将这些请求转发给代理服务器。
  3. 请求被代理服务器处理
    请求会先到达代理服务器,代理服务器负责处理这些请求,将请求转发给真实的API服务器。
  4. API服务器响应请求
    API服务器处理完请求后会返回响应结果,响应结果会先被发往代理服务器,再从代理服务器发往客户端浏览器,最终将结果展示在页面上。

八、Vue代理没有生效

在Vue代理过程中,我们有时候会发现代理规则没有生效,这可能是因为我们没有正确地配置代理规则,或者是因为webpack-dev-server没有正确地读取我们的配置文件。解决这个问题,通常可以采用如下办法:

  1. 确认代理规则是否正确设置
    我们可以在vue.config.js中对代理规则进行调整,并确保调整后的规则已经被正确地读取:
    // vue.config.js
    module.exports = {
      devServer: {
        proxy: {
          '/api': {
            target: 'http://localhost:3000',
            changeOrigin: true,
            pathRewrite: {
              '^/api': ''
            }
          }
        }
      }
    }
    
  2. 确认代理服务器是否正常运行
    我们可以使用curl等工具尝试直接访问API服务器来确认其是否正常运行:
    curl http://localhost:3000/api/test
    
    如果API返回了正确的结果,则表示代理服务器已经正常运行。
  3. 确认webpack-dev-server是否正确读取了配置文件
    我们可以在命令行中执行如下命令,来检查webpack-dev-server是否正确地读取了配置文件:
    vue-cli-service serve --open --mode development
    
    如果此时代理规则已经生效,则我们可以进一步排查其他问题。

九、Vue代理网关

Vue代理网关可以理解为我们的中间件栈,当一个API请求到达代理服务器时,它会先经过一系列的中间件处理,最终到达真实的API服务器。我们可以在中间件中添加一些处理逻辑,例如:

// vue.config.js
module.exports = {
  devServer: {
    before(app){
      app.use((req, res, next) => {
        console.log(`${req.method} ${req.url}`)
        next()
      })
    },
    proxy: 'http://localhost:3000',
  }
}

这里我们通过before选项向webpack-dev-server注册了一个全局的中间件,用于记录所有API请求的方法和路径。

十、Vue代理模式源码

Vue代理是通过webpack-dev-server提供的中间件和代理机制来实现的,我们可以查看其源码来深入了解其实现原理。以下是其中的一部分代码:

// webpack-dev-server/lib/Server.js
class Server {
  constructor(options = {}) {
    // 配置各种中间件
    this.middleware = []
    this.setupMiddleware()
    // 配置代理规则
    this.proxy = []
    // 启动服务器
    this.server = http.createServer(this.app)
    this.server.on('error', err => {
      console.log(err)
    })
    this.server.listen(options.port, options.host, () => {
      console.log(`Listening on ${options.host}:${options.port}`)
    })
  }
  setupMiddleware() {
    // 设置WebSocket服务器
    this.middleware.push(websocket(this))
    // 设置静态文件服务器
    this.middleware.push(this.serveStatic())
    // 设置热更新服务器
    this.middleware.push(this.serveHMR())
    // 设置API代理
    this.middleware.push(this.createProxyMiddleware())
    // 设置HTML文件服务器
    this.middleware.push(this.serveAssets())
  }
  createProxyMiddleware() {
    const proxy = httpProxy.createProxyServer()
    return (req, res, next) => {
      // 匹配代理规则
      const matchResult = this.matchProxy(req)
      if (!matchResult) {
        return next()
      }
      // 转发请求到代理服务器
      const {target, path, rewrite} = matchResult
      req.url = rewrite(req.url)
      req.headers.host = target.host
      proxy.web(req, res, {target: target.href})
    }
  }
}

这里我们可以看到,webpack-dev-server通过一系列中间件的组合实现了Vue代理的基本功能,通过代理中间件和API代理等组件,它可以将API请求根据规则转发到指定的API服务器上,从而实现跨越请求和服务代理等功能。