Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HMR clientPort option ignored in normal mode #3737

Closed
NickClark opened this issue Jun 9, 2021 · 5 comments · Fixed by #4332
Closed

HMR clientPort option ignored in normal mode #3737

NickClark opened this issue Jun 9, 2021 · 5 comments · Fixed by #4332
Labels
enhancement New feature or request

Comments

@NickClark
Copy link

Describe the bug

When using Vite behind a proxy, it would be nice to set the client port. I had it working when using SvelteKit, but I decide Vite alone would be more appropriate for my SPA. Found that the same server.hmr configuration didn't work. It appears that clientPort is only considered if in middleware mode.

Reproduction

import { defineConfig } from "vite";
import svelte from "@sveltejs/vite-plugin-svelte";

export default defineConfig(({ command, mode }) => {
  const isProduction = mode === "production";

  return {
    plugins: [svelte()],
    server: {
      strictPort: true,
      hmr: {
        clientPort: 443,
        port: 5001,
        protocol: "wss",
        path: "/vite",
      },
    },
  };
});

System Info

  System:
    OS: Linux 4.19 Ubuntu 20.04.1 LTS (Focal Fossa)
    CPU: (24) x64 AMD Ryzen 9 5900X 12-Core Processor
    Memory: 10.69 GB / 24.99 GB
    Container: Yes
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.2.0 - ~/.asdf/installs/nodejs/16.2.0/bin/node
    npm: 7.13.0 - ~/.asdf/installs/nodejs/16.2.0/bin/npm
  npmPackages:
    vite: ^2.3.7 => 2.3.7
@asaf
Copy link

asaf commented Jun 26, 2021

this is important, without this it's impossible to run vite behind an https proxy,

I had to workaround this by patching client.js:

const socket = new WebSocket(`wss://my-host/myapp`, 'vite-hmr');

@plashenkov
Copy link

Hmmm, for some reason, using server.hmr.port = 443 works for me. I'm using Vite dev server behind an nginx, and autoreloading seems to work. I do not know internals though.

Nginx config:

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name (...);
  ssl_certificate (...);
  ssl_certificate_key (...);
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection 'upgrade';
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  location /admin {
    proxy_pass http://vite_server:3000;
  }
}

Vite config:

export default defineConfig({
  plugins: [vue()],
  base: '/admin/',
  server: {
    host: true,
    port: 3000,
    strictPort: true,
    hmr: {
      port: 443,
    }
  }
})

Also, on my local dev machine Vite dev server throws an error when server.port = 80 (as expected), but it starts without problem when server.hmr.port = 80. Does this mean that it doesn't try to start HMR server on port 80 and just uses this value to pass it to a browser?

@plashenkov
Copy link

Okay, if I understand the code correctly, in standard, non-middleware mode, there is no separate server for HMR created (until you specially create it and specify in server.hmr.server option):

const hmr = typeof config.server.hmr === 'object' && config.server.hmr
const wsServer = (hmr && hmr.server) || server
if (wsServer) {
wss = new WebSocket.Server({ noServer: true })
wsServer.on('upgrade', (req, socket, head) => {
if (req.headers['sec-websocket-protocol'] === HMR_HEADER) {
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit('connection', ws, req)
})
}
})
} else {

And here you can see that the server.hmr.port option is taken (see the line after else) and then simply passed to the client side:

if (config.server.middlewareMode) {
if (typeof config.server.hmr === 'object') {
port = config.server.hmr.clientPort || config.server.hmr.port
}
port = String(port || 24678)
} else {
port = String(options.port || config.server.port!)
}

For the middleware mode, server.hmr.port is used to create a real http server on that port. As for the client side, server.hmr.clientPort can be used to override the real server port value.

To summarize

In non-middleware mode the server.hmr.port option can be used for overriding, for middleware mode — server.hmr.port is really used, and server.hmr.clientPort can be used for overriding.

It looks like there can be confusion with such fuzzy usage of options, and some unification would be fine.

@johnnysprinkles @Shinigami92

@plashenkov
Copy link

@Cretezy Great, it works! Thank you!

@johnnysprinkles
Copy link
Contributor

Thanks for fixing, when I added that I didn't really know what middlewareMode is (actually I guess I still don't), and just got it working for my own use case.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants