使用react-create-app createProxy创建后端代理一直提示404的解决办法

项目场景:

由于需要进行前后端联调,而后端因为CORS原因必须解决同源问题,需要前端调整来代理后端流量

问题描述

看到官方文档Proxying API Requests in Development
有写如何配置代理的方案,试过直接在packages.json中添加proxy键值对,发现不能修改Origin和Host,故而专用setupProxy方式。但是参考setupProxy方式操作时不起作用,一直提示404,无法找到对应api。
并且在编译过程提示:

(node:517060) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:517060) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.

前置说明

项目使用TypeScript开发,以下为相关组件版本

  • node版本v18.15.0
  • npm版本9.5.0
  • 依赖项版本如下:
    {
    'dependencies': {
    	...
        "http-proxy-middleware": "^3.0.0",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "react-scripts": "5.0.1",
        }
    }
    

网上见到的处理办法包括但不限于

  1. 版本过低,react-scripts低于2.0.0时需要修改createProxy.js代码

    const proxy = require('http-proxy-middleware')
    
    module.exports = function(app) {
      app.use(
        proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
          target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
          changeOrigin: true, //控制服务器接收到的请求头中host字段的值
          pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
        }),
        proxy('/api2', { 
          target: 'http://localhost:5001',
          changeOrigin: true,
          pathRewrite: {'^/api2': ''}
        })
      )
    }
    

    修改为

    const { createProxyMiddleware } = require("http-proxy-middleware")
    module.exports = function (app) {
      app.use(
        createProxyMiddleware("/api1",{
          target: "http://localhost:5000", //配置转发目标地址(能返回数据的服务器地址)
          changeOrigin: true, //控制服务器接收到的请求头中host字段的值
          pathRewrite: { "^/api1": "" }, 
        }),
        createProxyMiddleware("/api2",{
          target: "http://localhost:5001", //配置转发目标地址(能返回数据的服务器地址)
          changeOrigin: true, //控制服务器接收到的请求头中host字段的值
          pathRewrite: { "^/api2": "" }, 
        })
      )
    }
    

    https://github.com/facebook/create-react-app/issues/11860

  2. 修改create-react-app版本

  3. 直接修改node-modules下的react-script源码,将node_modules/react-scripts/config/webpackDevServer.config.js中的onBeforeSetupMiddleware修改为setupMiddlewares

    onBeforeSetupMiddleware(devServer) {
      // Keep `evalSourceMapMiddleware`
      // middlewares before `redirectServedPath` otherwise will not have any effect
      // This lets us fetch source contents from webpack for the error overlay
      devServer.app.use(evalSourceMapMiddleware(devServer));
    
      if (fs.existsSync(paths.proxySetup)) {
        // This registers user provided middleware for proxy reasons
        require(paths.proxySetup)(devServer.app);
      }
    },
    onAfterSetupMiddleware(devServer) {
      // Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
      devServer.app.use(redirectServedPath(paths.publicUrlOrPath));
    
      // This service worker file is effectively a 'no-op' that will reset any
      // previous service worker registered for the same host:port combination.
      // We do this in development to avoid hitting the production cache if
      // it used the same host and port.
      // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
      devServer.app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
    },
    

    改为

    setupMiddlewares: (middlewares, devServer) => {
      if (!devServer) {
        throw new Error('webpack-dev-server is not defined')
      }
    
      if (fs.existsSync(paths.proxySetup)) {
        require(paths.proxySetup)(devServer.app)
      }
    
      middlewares.push(
        evalSourceMapMiddleware(devServer),
        redirectServedPath(paths.publicUrlOrPath),
        noopServiceWorkerMiddleware(paths.publicUrlOrPath)
      )
    
      return middlewares;
    },
    

上述方法均不起作用,且无法看到错误信息

排查及处置:

根据源码和编译前webpack的报错提示

(node:517060) [DEP_WEBPACK_DEV_SERVER_ON_AFTER_SETUP_MIDDLEWARE] DeprecationWarning: 'onAfterSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:517060) [DEP_WEBPACK_DEV_SERVER_ON_BEFORE_SETUP_MIDDLEWARE] DeprecationWarning: 'onBeforeSetupMiddleware' option is deprecated. Please use the 'setupMiddlewares' option.

我们找到源码位置,在项目node_modules/react-scripts/config/webpackDevServer.config.js文件中,参考导出函数onBeforeSetupMiddleware的内容,我们在其内部下断点,输出paths.proxySetup,并且捕获require(paths.proxySetup)(devServer.app);产生的异常。根据这一方法进行检查,发现paths.proxySetup只解析src/setupProxy.js不解析src/setupProxy.ts,需要修改代码文件名及内部代码规范。

而后根据后端响应的路由信息,检查到代理需要提供后缀或者对路径进行rewrite,

const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
    app.use(
        '/api',
        createProxyMiddleware({
            target : 'http://localhost:8080/api',
            changeOrigin: true,
        })
    );
};

/api添加到target对应后端地址的路径上即可解决404问题。

总结

  1. 使用setupProxy.js文件名
  2. 注意代理路径问题,可以联合后端响应一起调试
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值