Webpack-dev-server: Websocket connection ignores the publicPath parameter

Created on 19 Apr 2019  路  7Comments  路  Source: webpack/webpack-dev-server

  • Operating System:
  • Node Version: 10.15.3
  • NPM Version: 6.4.1
  • webpack Version: 4.30.0
  • webpack-dev-server Version: 3.3.1
  • [x] This is a bug
  • [ ] This is a modification request

Code

// webpack.config.js
const djangoPort = 9000;
const port = 8000;

const common = {
//..
devServer: {
        historyApiFallback: true,
        publicPath: `http://localhost:${port}/`,
        proxy: {
            '*': `http://localhost:${djangoPort}`
        },
        headers: {
            'Access-Control-Allow-Origin': '*'
        },
        port: port
    },
}

common.output.publicPath = `http://localhost:${port}/`;
module.exports = common;

Summary

Hello,

I have django project that uses javascript assets from a webpack-dev-server instance.
The django app runs on localhost:9000 and webpack-dev-sever runs on localhost:8080.
In development, the django template loads static assets from localhost:8080.

The problem is that the hot reload code tries to connect to ws://localhost:9000 instead of 8080, and since the request is rejected by the django server, it gets stuck in an infinite loop.

Failed connection
image

Infinite loop
image

Expected Behavior

I think when setting the devServer:publicPath to http://localhost:8080 it should also do the websocket connection to that port.

Actual Behavior

The hot reload code tries to connect to ws://localhost:9000 instead of 8080

For Bugs; How can we reproduce the behavior?

I tried setting the sockPath parameter, but that only appends to ws://localhost:9000.

In a project with older dependencies, it works as expected, and connects to ws://localhost:8080.
These are the dependencies where it works.

    "webpack": "4.20.1",
    "webpack-cli": "3.1.1",
    "webpack-dev-server": "3.1.14",

I think in webpack-dev-server version 3.1.14 the sockPath parameter was not yet available.

Doing it in reverse works. By connecting to localhost:8080 it proxies the requests to django on localhost:9000.
The problem in doing this is that my docker setup is broken. If run webpack-dev-server and django in separate containers, webpack-dev-server doesn't know where to proxy.

Most helpful comment

Also publicPath should be path, not domain, it is path

It is not clear which 'publicPath' parameter you are referring to in your reply, as the parameter applies to both output and devServer. In either case, the webpack and webpack-dev-server documentation both allow absolute or relative paths. In fact, the webpack-dev-server documentation specifies a full URL will be used to server content.

In regards to the original problem of the websocket connecting to the wrong location, I faced the same problem after trying an update from version 3.2.6 to 3.3.1. I load the assets served by webpack-dev-server on a different host:port from my web application. Before the update, the development assets loaded from the development servers host:port. Following the change, all websocket requests switched to originate from the host:port of the web application. I was able to resolve the issue by adding the devServer.public parameter to 'host:port' matching the development server.

Here is an excerpt from my working configuration, where I run the application on https://subdomain.localhost.

let custompaths = {
    host: 'https://subdomain.localhost:9150/assets/dist/',
    port: 9150,
    publicdomain: 'subdomain.localhost:9150'
};

module.exports = {
    output: {
        publicPath: custompaths.host
    },
    devServer: {
        allowedHosts: [
            '.localhost'
            '127.0.0.1'
        ],
        contentBase: path.join( __dirname, '../dist' ),
        headers: {
            'Access-Control-Allow-Origin': '*'
        },
        hotOnly: true,
        https: true,
        historyApiFallback: true,
        inline: true,
        https: {
            key: fs.readFileSync( 'assets/ssl/subdomain.localhost.key' ),
            cert: fs.readFileSync( 'assets/ssl/subdomain.localhost.cer' )
        },
        port: custompaths.port,
        public: custompaths.publicdomain,
        publicPath: custompaths.host
    },
    module: { ... }
}

All 7 comments

Can you create minimum reproducible test repo, i think it is problem in configuration

Also publicPath should be path, not domain, it is path

I think you can setup proxy for handle statics for python server

Hey, thanks for tips 馃槃 .

I managed to make a minimum reproducible repo:
https://github.com/slbucur/test_wds_issue_1809

It's available on gitpod:
https://gitpod.io/#https://github.com/slbucur/test_wds_issue_1809

image

If you open the browser for the service running on 9000 (django), you should see the infinite loop.
image

If you open it on 8080, there the hot reload works correctly.
image

I had to change the config a bit because accessing ports on gitpod is with {port}-url.

Also publicPath should be path, not domain, it is path

It is not clear which 'publicPath' parameter you are referring to in your reply, as the parameter applies to both output and devServer. In either case, the webpack and webpack-dev-server documentation both allow absolute or relative paths. In fact, the webpack-dev-server documentation specifies a full URL will be used to server content.

In regards to the original problem of the websocket connecting to the wrong location, I faced the same problem after trying an update from version 3.2.6 to 3.3.1. I load the assets served by webpack-dev-server on a different host:port from my web application. Before the update, the development assets loaded from the development servers host:port. Following the change, all websocket requests switched to originate from the host:port of the web application. I was able to resolve the issue by adding the devServer.public parameter to 'host:port' matching the development server.

Here is an excerpt from my working configuration, where I run the application on https://subdomain.localhost.

let custompaths = {
    host: 'https://subdomain.localhost:9150/assets/dist/',
    port: 9150,
    publicdomain: 'subdomain.localhost:9150'
};

module.exports = {
    output: {
        publicPath: custompaths.host
    },
    devServer: {
        allowedHosts: [
            '.localhost'
            '127.0.0.1'
        ],
        contentBase: path.join( __dirname, '../dist' ),
        headers: {
            'Access-Control-Allow-Origin': '*'
        },
        hotOnly: true,
        https: true,
        historyApiFallback: true,
        inline: true,
        https: {
            key: fs.readFileSync( 'assets/ssl/subdomain.localhost.key' ),
            cert: fs.readFileSync( 'assets/ssl/subdomain.localhost.cer' )
        },
        port: custompaths.port,
        public: custompaths.publicdomain,
        publicPath: custompaths.host
    },
    module: { ... }
}

I confirm that adding the public parameter as localhost:8080 fixes the issue.

I fixed the reproducing repo with this commit:
https://github.com/slbucur/test_wds_issue_1809/commit/7130fffe0f4d491689c6bd1a2b3ebea69847bebf

Now we support sockHost, sockPort and sockPath for this cases, also we fix regression in 3.3.1, if you still have problem please open new issue with reproducible test repo, thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hnqlvs picture hnqlvs  路  3Comments

eyakcn picture eyakcn  路  3Comments

uMaxmaxmaximus picture uMaxmaxmaximus  路  3Comments

tulika21-zz picture tulika21-zz  路  3Comments

MJ111 picture MJ111  路  3Comments