0

I'm facing this problem for a websocket proxy ws/**:

<i> [webpack-dev-server] [HPM] Upgrading to WebSocket
<e> [webpack-dev-server] [HPM] WebSocket error: Error: read ECONNRESET
<e>     at TCP.onStreamRead (node:internal/stream_base_commons:217:20) {
<e>   errno: -4077,
<e>   code: 'ECONNRESET',
<e>   syscall: 'read'
<e> }

I have attached my configuration and package versions at the very bottom.

Originally migrated webpack from version 4 to version 5. This problem was not observed in version 4. Even now, switching to the old version of the project, this error does not occur when working with the /ws/** socket.

The web socket itself receives data normally, but the IDE console displays this error every time I interact with the web socket. I tried:

  • add fields webSocketTransport, webSocketURL and webSocketServer
  • update webpack packages to the latest versions
  • directly install the ws package of the latest version

Packages versions:

"webpack": "^5.89.0",
"webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"html-webpack-plugin": "^5.6.0",

Webpack configuration:

"use strict";

const webpack = require("webpack");
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CspHtmlWebpackPlugin = require("csp-html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { DefinePlugin } = require('webpack');

const Xliff2Json = require("./Xliff2Json");

const ip = require("ip");
const DEV_IP_ADDR = ip.address();
const DEV_PORT = 5002;
const ASSET_PATH = process.env.ASSET_PATH || "/";
const API_DOMAIN = "";
const API_PORT = "";

const isDevelopment = process.argv[process.argv.indexOf('--mode') + 1] === 'development';

const webpackConfig = {
    entry: ["@babel/polyfill", "./src/index.jsx"],
    output: {
        filename: isDevelopment ? "[name].bundle.js" : "[contenthash].bundle.js",
        path: path.resolve(__dirname, "dist"),
        publicPath: "/",
        library: "app",
    },
    devServer: {
        port: DEV_PORT,
        host: DEV_IP_ADDR,
        historyApiFallback: true,
        devMiddleware: {
            publicPath: ASSET_PATH,
            stats: "minimal",
        },
        client: {
            logging: "info",
            overlay: {
                errors: true,
                warnings: false,
                runtimeErrors: true,
            },
            webSocketTransport: 'ws',
            webSocketURL: `ws://${DEV_IP_ADDR}:${DEV_PORT}/ws`,
        },
        webSocketServer: 'ws',
        static: {
            directory: path.join(__dirname, "dist"),
        },
        open: true,
        hot: true,
        liveReload: true,
        proxy: [
            {
                context: [
                    "/api/**",
                    "/stream/sse/**",
                    "/download/**"
                ],
                target: "https://my-instance.com",
                secure: false,
                changeOrigin: true,
            },
            {
                context: [
                    "/ws/**",
                    "/stream/ws/**"
                ],
                target: "wss://my-instance.com",
                ws: true,
                secure: false,
                changeOrigin: true,
            },
        ],
    },
    module: {
        rules: [
            {
                test: /\.(css|scss)$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "postcss-loader",
                    "sass-loader"
                ],
            },
            {
                test: /\.(jsx|js)$/,
                exclude: /(node_modules)/,
                use: {
                    loader: "babel-loader",
                },
            },
            {
                test: /\.(png|svg|jpg|gif|woff|woff2|eot|ttf|otf)$/,
                type: 'asset/resource',
            }
        ],
    },
    resolve: {
        extensions: [".js", ".jsx"],
    },
    plugins: [
        new webpack.ProgressPlugin(),
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: isDevelopment ? "[id].css" : "[contenthash].css",
            ignoreOrder: true
        }),
        new HtmlWebpackPlugin({
            inject: true,
            hash: true,
            favicon: "./src/static/images/favicon.png",
            template: "./src/index.html",
            filename: "index.html",
        }),
        new DefinePlugin({
            API_DOMAIN: `"${API_DOMAIN}"`,
            API_PORT: `"${API_PORT}"`,
        }),
        new CspHtmlWebpackPlugin(
            {
                "default-src": ["'self'", "my-sentry-backend.com", "wss:", "ws:"],
                "base-uri": "'self'",
                "object-src": "'none'",
                "frame-src": "'none'",
                "worker-src": "blob:",
                "img-src": ["'self'", "data:"],
                "script-src": ["'self'", "'unsafe-eval'"],
                "style-src": ["'unsafe-inline'", "'self'"],
            },
            {
                enabled: true,
                hashingMethod: "sha256",
                hashEnabled: {
                    "worker-src": true,
                    "script-src": true,
                    "style-src": true,
                },
                nonceEnabled: {
                    "worker-src": true,
                    "script-src": true,
                    "style-src": false,
                },
            }
        )
    ],
};

if (isDevelopment) {
    webpackConfig.devtool = 'inline-cheap-module-source-map';
}

module.exports = webpackConfig;

1 Answer 1

0

In my case the problem was the same name of the default webpack websocket and the mask in the proxy (/ws). Adding a new segment to the mask helped and instead of “/ws/**” I got “ws/api/**”.

{
    context: [
        "/ws/api/**",
        "/stream/ws/**"
    ],
    target: "wss://my-instance.com",
    ws: true,
    secure: false,
    changeOrigin: true,
},
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.