webpack 代理多个后台服务-proxy

2,613 阅读3分钟

让你明明白白学知识,有代码,有讲解,抄的走,学的会!

背景: 我们的系统比较庞大,且臃肿,稳定性,扩展性都受影响, 后端往往会将服务拆分为N个子服务, 即 微服务 化

image.png

前端可能访问的接口, 可能是由上面N个服务提供, 一般每个服务是有一个服务名;

针对这种场景的联调,一般在线上 dev 环境进行, 所有服务都同步部署到线上; 一旦出现问题, 后台只能通过 log 进行debug, 如果想要后台在本地进行debug , 怎么做?

webpack 的 webpack-dev-server 其实提供的就是 一个本地服务的能力, 可以利用 proxy 将本地的请求都代理到 同事的机子上, 就实现了本地调试

优点:

  • 线上dev 环境一般只有一个, 如果频繁的发布版本 则会干扰其他人联调
  • 方便接口debug, 后台可以直接在 开发工具进行断点调试 (如果存在前后端代码一起重构, 则十分有必要, 因为不确定修改后的结果是否和之前有较大偏差)
  • 部分接口使用线上的, 部分直接代理到 局域网内 其他电脑 , 足够灵活

demo

有1个前端正在开发的服务, 3001 有3个后台服务, 8002, 8003, 8004

webpack.config.js

const path = require("path")
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: path.resolve(__dirname, '/src/index.js'),
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'html-webpack-plugin',
      template: "./index.html", // 使用我们自己指定的 template
      minify: {
        collapseWhitespace: true
      },
      hash: true
    })
  ],
  devServer: { // 开发服务器配置
    contentBase: "./dist",
    hot: true,
    port: 3001, // 更改 监听端口
    filename: "[name].bundle.js",
    open: true,  // 启动服务,就打开运行服务
    proxy: {
      '/api/saas-server-product': {
        target: 'http://localhost:8002',
        changeOrigin: true,
        pathRewrite: { '^/api/saas-server-product': '/api/product'}
      },
      '/api/saas-server-order': {
        target: 'http://localhost:8003',
        pathRewrite: { '^/api/saas-server-order': '/api/order'},
        changeOrigin: true,
      },
      '/api/saas-server-crm': {
        target: 'http://localhost:8004',
        pathRewrite: { '^/api/saas-server-crm': '/api/email'},
        changeOrigin: true,
      }
    }
  }
}

最主要的就是 proxy 配置

index.html

<body>
  <p >token-- <span class="content"></span></p>
  <p >第二个系统返回的数据 -- <span class="content"></span></p>
  <p >第三个系统返回的数据-- <span class="content"></span></p>
</body>

src/index.js

import axios from "axios"

const listEl = document.querySelectorAll(".content")

const qq  ='123456789@qq.com'

const fn1 = () => {
  return axios.get('/api/saas-server-product/login/getToken', {
    headers: {
      token: qq
    }
  })
}


async function start() {
  const {data: {token}} = await fn1()

  listEl[0].innerHTML = token

  const fn2 = await axios.get('/api/saas-server-order/price/getPrice', {
    headers: {
      token,
      msg: 'server2'
    }
  })

  listEl[1].innerHTML = JSON.stringify(fn2.data)

  const fn3 = await axios.post('/api/saas-server-crm/sendEmail', {
    headers: {
      token,
      msg: 'server3'
    }
  })

  listEl[2].innerHTML = JSON.stringify(fn3.data)
}

start()

模拟后台服务 8002, 8003, 8004 其实代码是一样的 app-1.js

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('product服务')
})

app.get('/api/product/login/getToken', (req, res) => {
  res.json({
    url: req.url,
    message: '第一个服务,返回一个token',
    token: '666666'
  })
})

app.listen(8002, ()=> {
  console.log('product服务, http://localhost:8002')
})

app-2.js

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('order服务')
})

app.get('/api/order/price/getPrice', (req, res) => {
  res.json({
    url: req.url,
    message: '第2个服务,返回token',
    token: '666666',
    price: 2.12
  })
})

app.listen(8003, ()=> {
  console.log('order服务, http://localhost:8003')
})

app-3.js

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('crm服务')
})

app.post('/api/email/sendEmail', (req, res) => {
  res.json({
    url: req.url,
    message: '第3个服务,邮箱发送成功',
    token: '666666',
  })
})

app.listen(8004, ()=> {
  console.log('email服务, http://localhost:8004')
})

效果图

image.png

目前 前端已经可以调用3个不同的后台服务, 已经实现我们的目标