You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack dev server启用HMR时如何正确代理WebSocket请求

Webpack Dev Server WebSocket代理报错ERR_STREAM_WRITE_AFTER_END问题处理

问题场景

  • 技术栈:基于Webpack 5构建React前端项目,后端作为独立进程运行,通过Webpack Dev Server(简称WDS)将前端请求代理到后端服务
  • 异常现象:普通HTTP API请求代理正常,添加带ws: true参数的WebSocket代理规则后,本地访问页面时控制台每秒重复抛出流写入错误;即使移除客户端业务WebSocket连接代码,错误依然存在
  • 后续排查:修改业务WebSocket代理路径为/websocket规避路径冲突后,出现WebSocket连接失败问题;经原生静态页直连测试,后端WebSocket服务本身运行正常,判定异常来自WDS配置

初始报错日志

<i> [webpack-dev-server] [HPM] Upgrading to WebSocket
<e> [webpack-dev-server] [HPM] WebSocket error: Error [ERR_STREAM_WRITE_AFTER_END]: write after end
<e>     at new NodeError (node:internal/errors:372:5)
<e>     at _write (node:internal/streams/writable:319:11)
<e>     at Socket.Writable.write (node:internal/streams/writable:334:10)
<e>     at Sender.sendFrame (C:\code\line-up\line-up-client\node_modules\ws\lib\sender.js:469:20)
<e>     at Sender.close (C:\code\line-up\line-up-client\node_modules\ws\lib\sender.js:197:12)
<e>     at WebSocket.close (C:\code\line-up\line-up-client\node_modules\ws\lib\websocket.js:300:18)
<e>     at Receiver.receiverOnConclude (C:\code\line-up\line-up-client\node_modules\ws\lib\websocket.js:1114:18)
<e>     at Receiver.emit (node:events:527:28)
<e>     at Receiver.controlMessage (C:\code\line-up\line-up-client\node_modules\ws\lib\receiver.js:582:14)
<e>     at Receiver.getData (C:\code\line-up\line-up-client\node_modules\ws\lib\receiver.js:429:42) {
<e>   code: 'ERR_STREAM_WRITE_AFTER_END'
<e> }

初始配置与环境信息

初始代理配置

proxy: {
    '/api/*': {
        target: 'http://localhost:5150',
        pathRewrite: { '^/api': '' },
    },
    '/ws': {
        target: 'ws://localhost:5150',
        ws: true,
    }
},

服务信息

  • 后端HTTP服务监听地址:http://localhost:5150
  • 后端WebSocket端点:localhost:5150/ws

依赖版本

"webpack": "^5.72.1",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0"

已尝试无效方案

  • 将/ws代理的target改为http协议
  • 将target直接指向/ws路径
  • 为所有代理规则添加ws: true配置
  • 调整多组配置组合均未解决问题

解决方案

根因说明

  1. 初始循环报错:自定义/ws代理路径和WDS内置热更新(HMR)的默认WebSocket路径完全重合,代理规则拦截了HMR本身的WebSocket连接,导致连接反复断开重连抛出流写入错误。
  2. 路径修改后连接失败:WDS 4.x底层依赖http-proxy-middleware处理WebSocket代理时,默认未正确转发Origin头,且缺少对内置HMR连接的跳过逻辑。

可用代理配置

直接替换devServer中的proxy配置即可:

proxy: {
    '/api/*': {
        target: 'http://localhost:5150',
        pathRewrite: { '^/api': '' },
    },
    '/websocket': {
        target: 'http://localhost:5150',
        ws: true,
        changeOrigin: true,
        bypass: (req) => {
            // 跳过WDS自身的HMR WebSocket请求,避免被当前规则拦截
            if (req.headers.upgrade && req.url.startsWith('/ws')) {
                return req.url;
            }
        }
    }
},

极端场景兼容配置

如果上述配置仍存在连接异常,显式指定WDS客户端的HMR WebSocket地址,彻底和业务WebSocket路径隔离:

devServer: {
    // 其余原有配置保持不变
    client: {
        // 端口替换为本地WDS实际运行的端口,默认是8080
        webSocketURL: 'ws://localhost:8080/ws'
    }
}

验证方式

  • 重启WDS后控制台不再循环抛出ERR_STREAM_WRITE_AFTER_END错误
  • 客户端业务代码通过new WebSocket(ws://${window.location.host}/websocket)发起连接,即可正常对接后端WebSocket服务

内容的提问来源于stack exchange,提问作者tvandinther

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 02:27:29