Conversation
If they added |
setupHmrWsOptionCompat() returns early when `server.ws` is `false`, the same way it does for `server.hmr === false`. The early return is needed because the second half of the function aliases the deprecated `server.hmr.*` WebSocket options onto `server.ws.*`, which cannot work when `server.ws` is not an object. But it also skips the branch that reports the deprecated options, so with `server.ws: false` they are accepted, type-checked, and then dropped without a word. That contradicts the docs for `server.hmr`, which say these options "are automatically synced, so existing configurations will continue to work". Someone who sets `server.ws: false` and leaves `server.hmr.port` behind gets no signal that the setting does nothing. Split the combined early return and report the ignored keys through the same `console[method]` / VITE_DEPRECATION_TRACE path the surrounding deprecation warnings already use, deduped per key since this runs on every merge and config-resolution pass. `server.ws: false` still disables the WebSocket server, and the ignored options are still not applied, which is the correct behaviour for that option. Only the silence is removed. Adds two regression tests: one asserting the warning is emitted, one asserting it is not emitted for an `server.hmr` object that carries no WebSocket options.
The typecheck step of the Lint CI job failed with: src/node/utils.ts(1458,40): error TS18048: 'serverConfig.hmr' is possibly 'undefined'. src/node/utils.ts(1458,40): error TS7053: Element implicitly has an 'any' type because expression of type '"path" | "server" | ...' can't be used to index type 'boolean | HmrOptions'. Capture serverConfig.hmr in a local const and narrow it via isObject() so TypeScript resolves it to HmrOptions when indexing with wsOptionKeys. No behaviour change.
- warn about ignored `server.hmr.server` only when `server.ws === false`, `command === 'serve'` and `server.hmr.server` is set; no longer reports the other deprecated `server.hmr.*` keys - forward `isPreview` from `resolveConfig` into `resolveServerOptions` so `vite preview` (which has no HMR server) does not emit the warning, and keep `mergeConfig` and `vite build` silent - add a test asserting no warning on the preview path
940415f to
f133622
Compare
|
You're right — with The one case I'd keep it for is that Losing You were also right about the gates: the first version warned on Pushed as Happy to drop |
What is this PR solving?
setupHmrWsOptionCompat()returns early whenserver.wsisfalse, in the same branch asserver.hmr === false. That early return exists because the rest of the function aliases the deprecatedserver.hmr.*options ontoserver.ws.*, which cannot work whenserver.wsisn't an object. The problem is that it also skips the warning. Withserver.ws: false, thoseserver.hmr.*options are accepted, type-checked, and then dropped with no message at all.Reproduction
Using
server.hmr.server, not host/port, since host/port no longer warn:Observed before the fix:
server.wsisfalse, the custom server is silently never attached, and nothing is printed. Expected: the same, plus a warning naming the option that was ignored and why.The same interaction shows up through
mergeConfig, since that path reachessetupHmrWsOptionCompattoo:hostandportappear in that snippet precisely because they no longer warn — it shows the descriptor behaviour that motivated the first revision, not a warning that fires today.What the fix does
The warning now fires only for
server.hmr.server, and only when a dev server actually starts. The guard is:server.hmr.serversurvives the narrowing because it isn't a socket parameter, it's the HMR transport.docs/config/server-options.md:216— "Whenserver.ws.serveris defined, Vite will process the WebSocket connection requests through the provided server." Withws: false,createWebSocketServerreturns a noop stub (guard atws.ts:123, stub spanningws.ts:124-144, closing atws.ts:145), sowsOptions/wsCustomServeratws.ts:149-150are never reached. Losing a port, host, or path is inferable from writingws: false; losing the transport is not.The other six socket keys (
protocol,host,port,clientPort,path,timeout) no longer warn at all — they were dropped after review, because writingserver.ws: falsealready means there is no socket to configure.preview.ts:138callsresolveConfig(inlineConfig, 'serve', 'production', 'production', true)— the fifth positional argument is a baretrue, which isisPreview. That is whyisPreviewhas to be threaded through intoresolveServerOptions(server/index.ts:1262signature, forwarded atserver/index.ts:1273), and why aserve-only gate was not enough: preview has no HMR, so an ungated warning would fire there too.The ignored options still do not take effect.
server.ws: falsekeeps the WebSocket server disabled; this change only reports that they were never going to be applied.Bare
mergeConfigpasses nocommand(utils.ts:1513-1515), so it stays silent. That is code-path reasoning, not something covered by a test.Alternatives considered
buildand preview, where it is meaningless.resolveServerOptionsis called unconditionally (config.ts:1923-1929), so the gating has to be explicit. The first version of this change warned onvite build.sapphi-red, who wrote: "If they addedserver.ws: falsethen, I don't think ignoringserver.hmr.portis a problem as there's no "port" to configure." Note thatserver.hmr.portis a socket parameter, whileserver.hmr.serveris the transport — the six socket keys were dropped on that basis, andserver.hmr.serveris the one kept.Tests
In
packages/vite/src/node/__tests__/config.spec.ts::1151— warns whenserver.hmr.serveris ignored due toserver.ws: false:1184— does not warn forserver.hmroptions thatserver.ws: falseimplies are ignored. This covers host and port only; the other socket keys are not test-covered.:1245— does not warn forserver.hmr.serveron build:1101— does not warn about ignoredserver.hmr.serverduring preview:1215— does not warn whenserver.hmrhas no HMR serverThe pre-existing test at
config.spec.ts:1076-1099is byte-identical to the pre-PR original (compared againstf1e44aab4~1); it has noconsole.warnspy and was not changed by this PR. BaremergeConfigsilence is not covered by a test.Measured locally:
config.spec.ts— 124 passed. Wider node suite — 945 passed, 3 skipped, 63 files. Formatting was checked withoxfmt --checkon the four changed files, not repo-wide.Why this was missed
There's already a test for the sync,
resolveConfig properly syncs hmr and ws, and it does cover the alias working. It only exercises the path whereserver.wsis left unset, so thews: falsebranch was never checked. #23511 looked at this same early return for #23506, but that report was about aTypeErrorfrom merging, and the fix only skipped the missing descriptor. The test added alongside it asserts the merge doesn't throw and nothing about the options surviving, so the silent discard stayed.AI disclosure
I used AI tools to help investigate this and to draft the change. I reviewed the resulting code, reproduced the bug myself at
39ddf7ccf7e7469ff6a3ba37bca38c32ea804d6ewith a scratch spec before touching anything, and confirmed the new tests fail on unmodifiedmainand pass with the change — the diff is inutils.tsplus the tests, and I understand and can explain all of it.