webpack之配置proxy篇

1,696 阅读3分钟

写在前面

项目是vue2+webpack构建的。在前端开发过程中,经常会碰到跨域的问题,下面我们来看看这个vue2+webpack构建的项目,是如何使用别人的接口,且不需要后端配置Nginx等东西搞定跨域问题的。

项目结构如下:

截屏2022-08-27下午5.43.27.png

我们的proxy配置得需要在webpack.config.js里面配置。我的项目下的是webpack5以上的版本,所以官方文档的链接在这里。当前,webpack4和webpack5版本的devServer.proxy这一个模块几乎一模一样。可以相继浏览一下文档.


例子:

基本情况

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

就是 对/api/users的请求将请求代理到http://localhost:3000/api/users


如果不希望传递/api,则需要重写路径:

重写 pathRewrites

module.exports = {
    // ...
    devServer: {
        '/api': {
            target: 'http://localhost:3000',
            pathRewrite: { '^/api': '' },
        }
    }
}

默认情况下,将不接受HTTPS 上运行且证书无效后端服务器。 如果需要,可以这样修改配置:

证书https secure

module.exports = {
    // ...
    devServer: {
        '/api': {
            target: 'https://other-server.example.com',
            secure: false,
        }
    }
}

如果不想代理所有内容,可以基于函数的返回值绕过代理。

例如: 对于浏览器请求,想要提供html页面,但是对于api请求,想要代理它。可以这样修改配置:

绕过原则 bypass

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'https://other-server.example.com',
                bypass: function (req, res, proxyOptions) {
                    // 可以自行去打印一下这三个参数, 一般用得最多的还是req.headers
                     
                    // 如果返回来的是html
                    if (req.headers.accept.indexOf('html') !== -1) {
                        return '/index.html' // 用我们写的index.html代理原接口返回的html
                    }
                    
                },
            }
        }
    }
}


多个路径代理到同一个目标

如果想将多个特定路径代理到同一目标,则可以使用一个或多个带有 context 属性的对象的数组:

module.exports = {
  //...
  devServer: {
    proxy: [
      {
        context: ['/auth', '/api'],
        target: 'http://localhost:3000',
      },
    ],
  },
};

root根代理 /

默认情况下不会代理对 root 的请求。 要启用根代理,应将 devMiddleware.index 选项指定为虚假值:

module.exports = {
  //...
  devServer: {
    devMiddleware: {
      index: false, // 指定启用根代理
    },
    proxy: {
      context: () => true,
      target: 'http://localhost:1234',
    },
  },
};

保留主机头来源

默认情况下,代理时会保留主机头的来源,可以将 changeOrigin 设置为 true 以覆盖此行为。 在某些情况下,例如使用 name-based virtual hosted sites,它很有用。

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

代理B站

比如说项目中,我要请求b站接口,可以通过设置proxy代理过去,绕过跨域。

比如:

接口: api.bilibili.com/x/web-inter…

.截屏2022-08-27下午6.23.36.png

.截屏2022-08-27下午6.23.09.png

简单配置

devServer: {
   proxy: {
    '/x': 'https://api.bilibili.com'
  }
}

接口写成

截屏2022-08-27下午6.25.44.png

以为可以通过了, 但是来了个403, 这个报错其实就是b站监测到我们的referer和origin不是来自他们自己的域名,给返回了403

那么解决方法就是把referer和origin都改成https://t.bilibili.com(他们信任的域名),就可以通过了。

.截屏2022-08-27下午6.28.33.png

具体写法是:

proxy: {
    '/x': {
      target: 'https://api.bilibili.com',
      secure: false,
      bypass: (req, res, proxyOptions) => {
        if (req.headers && req.headers.referer) {
          url = new URL(req.headers.referer);
          req.headers.origin = 'https://t.bilibili.com';
          req.headers.referer = 'https://t.bilibili.com';
        }
      }
}

这样就可以代理成功了。

.截屏2022-08-27下午6.30.17.png


写在后面

webpack proxy只能用作于开发阶段,临时解决本地请求服务器产生的跨域问题,并不适用线上环境。线上环境还需要后端Nginx设置一下跨域。

分享就是一种输出。