From 87bbb040cb5efc848234d9fb79634e15eae15e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Fri, 24 May 2024 10:18:43 +0200 Subject: [PATCH] refactor!: rename to HMRPayload to HotPayload and remove HMRBroadcaster (#16875) --- docs/guide/api-vite-environment.md | 4 +- packages/vite/src/client/client.ts | 4 +- packages/vite/src/client/overlay.ts | 2 +- packages/vite/src/module-runner/hmrHandler.ts | 10 +- packages/vite/src/module-runner/types.ts | 4 +- packages/vite/src/node/index.ts | 11 +-- packages/vite/src/node/plugins/esbuild.ts | 4 +- .../server/__tests__/pluginContainer.spec.ts | 2 +- packages/vite/src/node/server/environment.ts | 29 +++--- .../server/environments/nodeEnvironment.ts | 2 +- packages/vite/src/node/server/hmr.ts | 91 +++---------------- packages/vite/src/node/server/index.ts | 34 ++----- .../vite/src/node/server/middlewares/error.ts | 2 +- packages/vite/src/node/server/ws.ts | 23 ++--- .../src/node/ssr/runtime/__tests__/utils.ts | 2 +- .../node/ssr/runtime/serverHmrConnector.ts | 26 +++--- .../node/ssr/runtime/serverModuleRunner.ts | 4 +- packages/vite/src/shared/hmr.ts | 2 +- packages/vite/types/customEvent.d.ts | 2 +- .../{hmrPayload.d.ts => hotPayload.d.ts} | 4 +- playground/hmr-ssr/vite.config.ts | 17 ++-- playground/hmr/vite.config.ts | 17 ++-- playground/html/__tests__/html.spec.ts | 2 +- 23 files changed, 104 insertions(+), 194 deletions(-) rename packages/vite/types/{hmrPayload.d.ts => hotPayload.d.ts} (91%) diff --git a/docs/guide/api-vite-environment.md b/docs/guide/api-vite-environment.md index dcc9bf70b185f2..8c550587a02b34 100644 --- a/docs/guide/api-vite-environment.md +++ b/docs/guide/api-vite-environment.md @@ -48,7 +48,7 @@ class DevEnvironment { * Communication channel to send and receive messages from the * associated module runner in the target runtime. */ - hot: HMRChannel | null + hot: HotChannel | null /** * Graph of module nodes, with the imported relationship between * processed modules and the cached result of the processed code. @@ -816,7 +816,7 @@ export interface ModuleRunnerHMRConnection { * Configure how HMR is handled when this connection triggers an update. * This method expects that the connection will start listening for HMR updates and call this callback when it's received. */ - onUpdate(callback: (payload: HMRPayload) => void): void + onUpdate(callback: (payload: HotPayload) => void): void } ``` diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 9253802db6decd..88e2ad8e39875c 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -1,4 +1,4 @@ -import type { ErrorPayload, HMRPayload } from 'types/hmrPayload' +import type { ErrorPayload, HotPayload } from 'types/hotPayload' import type { ViteHotContext } from 'types/hot' import type { InferCustomEventPayload } from 'types/customEvent' import { HMRClient, HMRContext } from '../shared/hmr' @@ -172,7 +172,7 @@ const hmrClient = new HMRClient( }, ) -async function handleMessage(payload: HMRPayload) { +async function handleMessage(payload: HotPayload) { switch (payload.type) { case 'connected': console.debug(`[vite] connected.`) diff --git a/packages/vite/src/client/overlay.ts b/packages/vite/src/client/overlay.ts index 63f570be488efb..971577236dc3f0 100644 --- a/packages/vite/src/client/overlay.ts +++ b/packages/vite/src/client/overlay.ts @@ -1,4 +1,4 @@ -import type { ErrorPayload } from 'types/hmrPayload' +import type { ErrorPayload } from 'types/hotPayload' // injected by the hmr plugin when served declare const __BASE__: string diff --git a/packages/vite/src/module-runner/hmrHandler.ts b/packages/vite/src/module-runner/hmrHandler.ts index d46b8b9c5581d2..a0965f854354c6 100644 --- a/packages/vite/src/module-runner/hmrHandler.ts +++ b/packages/vite/src/module-runner/hmrHandler.ts @@ -1,18 +1,18 @@ -import type { HMRPayload } from 'types/hmrPayload' +import type { HotPayload } from 'types/hotPayload' import { slash, unwrapId } from '../shared/utils' import type { ModuleRunner } from './runner' // updates to HMR should go one after another. It is possible to trigger another update during the invalidation for example. export function createHMRHandler( runner: ModuleRunner, -): (payload: HMRPayload) => Promise { +): (payload: HotPayload) => Promise { const queue = new Queue() - return (payload) => queue.enqueue(() => handleHMRPayload(runner, payload)) + return (payload) => queue.enqueue(() => handleHotPayload(runner, payload)) } -export async function handleHMRPayload( +export async function handleHotPayload( runner: ModuleRunner, - payload: HMRPayload, + payload: HotPayload, ): Promise { const hmrClient = runner.hmrClient if (!hmrClient || runner.isDestroyed()) return diff --git a/packages/vite/src/module-runner/types.ts b/packages/vite/src/module-runner/types.ts index 165a593fa31654..59c45a57afba3f 100644 --- a/packages/vite/src/module-runner/types.ts +++ b/packages/vite/src/module-runner/types.ts @@ -1,5 +1,5 @@ import type { ViteHotContext } from 'types/hot' -import type { HMRPayload } from 'types/hmrPayload' +import type { HotPayload } from 'types/hotPayload' import type { HMRConnection, HMRLogger } from '../shared/hmr' import type { DefineImportMetadata, @@ -24,7 +24,7 @@ export interface ModuleRunnerHMRConnection extends HMRConnection { * Configure how HMR is handled when this connection triggers an update. * This method expects that connection will start listening for HMR updates and call this callback when it's received. */ - onUpdate(callback: (payload: HMRPayload) => void): void + onUpdate(callback: (payload: HotPayload) => void): void } export interface ModuleRunnerImportMeta extends ImportMeta { diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index ab9c606d8ae973..8f6f55ad26eb0f 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -145,10 +145,9 @@ export type { export type { HmrOptions, HmrContext, HotUpdateContext } from './server/hmr' export type { - HMRBroadcaster, - HMRChannel, - ServerHMRChannel, - HMRBroadcasterClient, + HotChannel, + ServerHotChannel, + HotChannelClient, } from './server/hmr' export type { FetchFunction, FetchResult } from 'vite/module-runner' @@ -157,7 +156,7 @@ export type { ServerModuleRunnerOptions } from './ssr/runtime/serverModuleRunner export type { BindCLIShortcutsOptions, CLIShortcut } from './shortcuts' export type { - HMRPayload, + HotPayload, ConnectedPayload, UpdatePayload, Update, @@ -165,7 +164,7 @@ export type { CustomPayload, PrunePayload, ErrorPayload, -} from 'types/hmrPayload' +} from 'types/hotPayload' export type { CustomEventMap, InferCustomEventPayload, diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index cf368094e4ed01..219a1f624a5df8 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -479,7 +479,7 @@ export async function reloadOnTsconfigChange( // any json file in the tsconfig cache could have been used to compile ts if ( path.basename(changedFile) === 'tsconfig.json' || - changedFile.endsWith('.json') /* + changedFile.endsWith('.json') /* TODO: the tsconfckCache?.clear() line will make this fail if there are several servers we may need a cache per server if we don't want all servers to share the reset leaving it commented for now because it should still work @@ -500,7 +500,7 @@ export async function reloadOnTsconfigChange( tsconfckCache?.clear() // force full reload - server.hot.send({ + server.ws.send({ type: 'full-reload', path: '*', }) diff --git a/packages/vite/src/node/server/__tests__/pluginContainer.spec.ts b/packages/vite/src/node/server/__tests__/pluginContainer.spec.ts index a92d38c7f01af9..b492d6d4494856 100644 --- a/packages/vite/src/node/server/__tests__/pluginContainer.spec.ts +++ b/packages/vite/src/node/server/__tests__/pluginContainer.spec.ts @@ -222,7 +222,7 @@ async function getDevEnvironment( // @ts-expect-error This plugin requires a ViteDevServer instance. config.plugins = config.plugins.filter((p) => !p.name.includes('pre-alias')) - const environment = new DevEnvironment('client', config) + const environment = new DevEnvironment('client', config, { hot: false }) await environment.init() return environment diff --git a/packages/vite/src/node/server/environment.ts b/packages/vite/src/node/server/environment.ts index 3aa773e8db47d3..f52b27b335b046 100644 --- a/packages/vite/src/node/server/environment.ts +++ b/packages/vite/src/node/server/environment.ts @@ -20,8 +20,8 @@ import { } from '../optimizer/optimizer' import { resolveEnvironmentPlugins } from '../plugin' import { EnvironmentModuleGraph } from './moduleGraph' -import type { HMRChannel } from './hmr' -import { createNoopHMRChannel, getShortName, updateModules } from './hmr' +import type { HotChannel } from './hmr' +import { createNoopHotChannel, getShortName, updateModules } from './hmr' import type { TransformResult } from './transformRequest' import { transformRequest } from './transformRequest' import type { EnvironmentPluginContainer } from './pluginContainer' @@ -32,7 +32,7 @@ import { import type { RemoteEnvironmentTransport } from './environmentTransport' export interface DevEnvironmentSetup { - hot?: false | HMRChannel + hot: false | HotChannel watcher?: FSWatcher options?: EnvironmentOptions runner?: FetchModuleOptions & { @@ -90,24 +90,24 @@ export class DevEnvironment extends BaseEnvironment { _crawlEndFinder: CrawlEndFinder /** - * HMR channel for this environment. If not provided or disabled, + * Hot channel for this environment. If not provided or disabled, * it will be a noop channel that does nothing. * * @example * environment.hot.send({ type: 'full-reload' }) */ - hot: HMRChannel + hot: HotChannel constructor( name: string, config: ResolvedConfig, - setup?: DevEnvironmentSetup, + setup: DevEnvironmentSetup, ) { let options = config.environments[name] ?? getDefaultResolvedEnvironmentOptions(config) - if (setup?.options) { + if (setup.options) { options = mergeConfig( options, - setup?.options, + setup.options, ) as ResolvedEnvironmentOptions } super(name, config, options) @@ -118,17 +118,16 @@ export class DevEnvironment extends BaseEnvironment { this.pluginContainer!.resolveId(url, undefined), ) - this.hot = setup?.hot || createNoopHMRChannel() - this.watcher = setup?.watcher + this.hot = setup.hot || createNoopHotChannel() + this.watcher = setup.watcher this._onCrawlEndCallbacks = [] this._crawlEndFinder = setupOnCrawlEnd(() => { this._onCrawlEndCallbacks.forEach((cb) => cb()) }) - const ssrRunnerOptions = setup?.runner || {} - this._ssrRunnerOptions = ssrRunnerOptions - setup?.runner?.transport?.register(this) + this._ssrRunnerOptions = setup.runner || {} + setup.runner?.transport?.register(this) this.hot.on('vite:invalidate', async ({ path, message }) => { invalidateModule(this, { @@ -138,8 +137,8 @@ export class DevEnvironment extends BaseEnvironment { }) const { optimizeDeps } = this.options.dev - if (setup?.depsOptimizer) { - this.depsOptimizer = setup?.depsOptimizer + if (setup.depsOptimizer) { + this.depsOptimizer = setup.depsOptimizer } else if (!isDepOptimizationEnabled(optimizeDeps)) { this.depsOptimizer = undefined } else { diff --git a/packages/vite/src/node/server/environments/nodeEnvironment.ts b/packages/vite/src/node/server/environments/nodeEnvironment.ts index 0e55fb8fe848ac..e4e76a1ba31eb2 100644 --- a/packages/vite/src/node/server/environments/nodeEnvironment.ts +++ b/packages/vite/src/node/server/environments/nodeEnvironment.ts @@ -6,7 +6,7 @@ import { asyncFunctionDeclarationPaddingLineCount } from '../../../shared/utils' export function createNodeDevEnvironment( name: string, config: ResolvedConfig, - options?: DevEnvironmentSetup, + options: DevEnvironmentSetup, ): DevEnvironment { return new DevEnvironment(name, config, { ...options, diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index 7f8f8e32206dc8..7f2fd70b7ad769 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -3,7 +3,7 @@ import path from 'node:path' import type { Server } from 'node:http' import { EventEmitter } from 'node:events' import colors from 'picocolors' -import type { CustomPayload, HMRPayload, Update } from 'types/hmrPayload' +import type { CustomPayload, HotPayload, Update } from 'types/hotPayload' import type { RollupError } from 'rollup' import { CLIENT_DIR } from '../constants' import { createDebugger, normalizePath } from '../utils' @@ -36,8 +36,6 @@ export interface HmrOptions { timeout?: number overlay?: boolean server?: Server - /** @internal */ - channels?: HMRChannel[] } export interface HotUpdateContext { @@ -68,26 +66,22 @@ interface PropagationBoundary { isWithinCircularImport: boolean } -export interface HMRBroadcasterClient { +export interface HotChannelClient { /** * Send event to the client */ - send(payload: HMRPayload): void + send(payload: HotPayload): void /** * Send custom event */ send(event: string, payload?: CustomPayload['data']): void } -export interface HMRChannel { - /** - * Unique channel name - */ - name: string +export interface HotChannel { /** * Broadcast events to all clients */ - send(payload: HMRPayload): void + send(payload: HotPayload): void /** * Send custom event */ @@ -99,7 +93,7 @@ export interface HMRChannel { event: T, listener: ( data: InferCustomEventPayload, - client: HMRBroadcasterClient, + client: HotChannelClient, ...args: any[] ) => void, ): void @@ -118,18 +112,6 @@ export interface HMRChannel { close(): void } -export interface HMRBroadcaster extends Omit { - /** - * All registered channels. Always has websocket channel. - */ - readonly channels: HMRChannel[] - /** - * Add a new third-party channel. - */ - addChannel(connection: HMRChannel): HMRBroadcaster - close(): Promise -} - export function getShortName(file: string, root: string): string { return file.startsWith(withTrailingSlash(root)) ? path.posix.relative(root, file) @@ -884,70 +866,20 @@ async function readModifiedFile(file: string): Promise { } } -export function createHMRBroadcaster(): HMRBroadcaster { - const channels: HMRChannel[] = [] - const readyChannels = new WeakSet() - const broadcaster: HMRBroadcaster = { - get channels() { - return [...channels] - }, - addChannel(channel) { - if (channels.some((c) => c.name === channel.name)) { - throw new Error(`HMR channel "${channel.name}" is already defined.`) - } - channels.push(channel) - return broadcaster - }, - on(event: string, listener: (...args: any[]) => any) { - // emit connection event only when all channels are ready - if (event === 'connection') { - // make a copy so we don't wait for channels that might be added after this is triggered - const channels = this.channels - channels.forEach((channel) => - channel.on('connection', () => { - readyChannels.add(channel) - if (channels.every((c) => readyChannels.has(c))) { - listener() - } - }), - ) - return - } - channels.forEach((channel) => channel.on(event, listener)) - return - }, - off(event, listener) { - channels.forEach((channel) => channel.off(event, listener)) - return - }, - send(...args: any[]) { - channels.forEach((channel) => channel.send(...(args as [any]))) - }, - listen() { - channels.forEach((channel) => channel.listen()) - }, - close() { - return Promise.all(channels.map((channel) => channel.close())) - }, - } - return broadcaster -} - -export interface ServerHMRChannel extends HMRChannel { +export interface ServerHotChannel extends HotChannel { api: { innerEmitter: EventEmitter outsideEmitter: EventEmitter } } -export function createServerHMRChannel(): ServerHMRChannel { +export function createServerHotChannel(): ServerHotChannel { const innerEmitter = new EventEmitter() const outsideEmitter = new EventEmitter() return { - name: 'ssr', send(...args: any[]) { - let payload: HMRPayload + let payload: HotPayload if (typeof args[0] === 'string') { payload = { type: 'custom', @@ -964,7 +896,7 @@ export function createServerHMRChannel(): ServerHMRChannel { }, on: ((event: string, listener: () => unknown) => { innerEmitter.on(event, listener) - }) as ServerHMRChannel['on'], + }) as ServerHotChannel['on'], close() { innerEmitter.removeAllListeners() outsideEmitter.removeAllListeners() @@ -979,13 +911,12 @@ export function createServerHMRChannel(): ServerHMRChannel { } } -export function createNoopHMRChannel(): HMRChannel { +export function createNoopHotChannel(): HotChannel { function noop() { // noop } return { - name: 'noop', send: noop, on: noop, off: noop, diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 8f8a66022df113..5b39f884db1f7a 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -79,13 +79,8 @@ import { ModuleGraph } from './mixedModuleGraph' import type { ModuleNode } from './mixedModuleGraph' import { notFoundMiddleware } from './middlewares/notFound' import { errorMiddleware } from './middlewares/error' -import type { HMRBroadcaster, HmrOptions } from './hmr' -import { - createHMRBroadcaster, - createServerHMRChannel, - handleHMRUpdate, - updateModules, -} from './hmr' +import type { HmrOptions } from './hmr' +import { createServerHotChannel, handleHMRUpdate, updateModules } from './hmr' import { openBrowser as _openBrowser } from './openBrowser' import type { TransformOptions, TransformResult } from './transformRequest' import { transformRequest } from './transformRequest' @@ -251,17 +246,9 @@ export interface ViteDevServer { watcher: FSWatcher /** * web socket server with `send(payload)` method - * @deprecated use `hot` instead - */ - ws: WebSocketServer - /** - * HMR broadcaster that can be used to send custom HMR messages to the client - * - * Always sends a message to at least a WebSocket client. Any third party can - * add a channel to the broadcaster to process messages * @deprecated use `environment.hot` instead */ - hot: HMRBroadcaster + ws: WebSocketServer /** * Rollup plugin container that can run plugin hooks on a given file * @deprecated use `environment.pluginContainer` instead @@ -455,11 +442,7 @@ export async function _createServer( : await resolveHttpServer(serverConfig, middlewares, httpsOptions) const ws = createWebSocketServer(httpServer, config, httpsOptions) - const ssrHotChannel = createServerHMRChannel() - const hot = createHMRBroadcaster().addChannel(ws).addChannel(ssrHotChannel) - if (typeof config.server.hmr === 'object' && config.server.hmr.channels) { - config.server.hmr.channels.forEach((channel) => hot.addChannel(channel)) - } + const ssrHotChannel = createServerHotChannel() const publicFiles = await initPublicFilesPromise const { publicDir } = config @@ -540,7 +523,6 @@ export async function _createServer( httpServer, watcher, ws, - hot, environments, pluginContainer, @@ -691,7 +673,7 @@ export async function _createServer( await Promise.allSettled([ watcher.close(), - hot.close(), + ws.close(), Promise.allSettled( Object.values(server.environments).map((environment) => environment.close(), @@ -963,7 +945,7 @@ export async function _createServer( httpServer.listen = (async (port: number, ...args: any[]) => { try { // ensure ws server started - hot.listen() + Object.values(environments).forEach((e) => e.hot.listen()) await initServer() } catch (e) { httpServer.emit('error', e) @@ -973,7 +955,7 @@ export async function _createServer( }) as any } else { if (options.hotListen) { - hot.listen() + Object.values(environments).forEach((e) => e.hot.listen()) } await initServer() } @@ -1179,7 +1161,7 @@ async function restartServer(server: ViteDevServer) { if (!middlewareMode) { await server.listen(port, true) } else { - server.hot.listen() + server.ws.listen() } logger.info('server restarted.', { timestamp: true }) diff --git a/packages/vite/src/node/server/middlewares/error.ts b/packages/vite/src/node/server/middlewares/error.ts index a4de10dc8c8d17..d5c326e0185a6d 100644 --- a/packages/vite/src/node/server/middlewares/error.ts +++ b/packages/vite/src/node/server/middlewares/error.ts @@ -2,7 +2,7 @@ import colors from 'picocolors' import type { RollupError } from 'rollup' import type { Connect } from 'dep-types/connect' import strip from 'strip-ansi' -import type { ErrorPayload } from 'types/hmrPayload' +import type { ErrorPayload } from 'types/hotPayload' import { pad } from '../../utils' import type { ViteDevServer } from '../..' diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts index 6b70d1fbea5e77..061ed270d5d337 100644 --- a/packages/vite/src/node/server/ws.ts +++ b/packages/vite/src/node/server/ws.ts @@ -9,11 +9,11 @@ import colors from 'picocolors' import type { WebSocket as WebSocketRaw } from 'ws' import { WebSocketServer as WebSocketServerRaw_ } from 'ws' import type { WebSocket as WebSocketTypes } from 'dep-types/ws' -import type { CustomPayload, ErrorPayload, HMRPayload } from 'types/hmrPayload' +import type { ErrorPayload, HotPayload } from 'types/hotPayload' import type { InferCustomEventPayload } from 'types/customEvent' -import type { ResolvedConfig } from '..' +import type { HotChannelClient, ResolvedConfig } from '..' import { isObject } from '../utils' -import type { HMRChannel } from './hmr' +import type { HotChannel } from './hmr' import type { HttpServer } from '.' /* In Bun, the `ws` module is overridden to hook into the native code. Using the bundled `js` version @@ -31,7 +31,7 @@ export type WebSocketCustomListener = ( client: WebSocketClient, ) => void -export interface WebSocketServer extends HMRChannel { +export interface WebSocketServer extends HotChannel { /** * Listen on port and host */ @@ -61,15 +61,7 @@ export interface WebSocketServer extends HMRChannel { } } -export interface WebSocketClient { - /** - * Send event to the client - */ - send(payload: HMRPayload): void - /** - * Send custom event - */ - send(event: string, payload?: CustomPayload['data']): void +export interface WebSocketClient extends HotChannelClient { /** * The raw WebSocket instance * @advanced @@ -198,7 +190,7 @@ export function createWebSocketServer( if (!clientsMap.has(socket)) { clientsMap.set(socket, { send: (...args) => { - let payload: HMRPayload + let payload: HotPayload if (typeof args[0] === 'string') { payload = { type: 'custom', @@ -223,7 +215,6 @@ export function createWebSocketServer( let bufferedError: ErrorPayload | null = null return { - name: 'ws', listen: () => { wsHttpServer?.listen(port, host) }, @@ -249,7 +240,7 @@ export function createWebSocketServer( }, send(...args: any[]) { - let payload: HMRPayload + let payload: HotPayload if (typeof args[0] === 'string') { payload = { type: 'custom', diff --git a/packages/vite/src/node/ssr/runtime/__tests__/utils.ts b/packages/vite/src/node/ssr/runtime/__tests__/utils.ts index 9d52ffa0c7cbd6..9a91992aa32fa2 100644 --- a/packages/vite/src/node/ssr/runtime/__tests__/utils.ts +++ b/packages/vite/src/node/ssr/runtime/__tests__/utils.ts @@ -76,7 +76,7 @@ export async function createModuleRunnerTester( ...config, }) t.environment = t.server.environments.ssr - t.runner = await createServerModuleRunner(t.environment, { + t.runner = createServerModuleRunner(t.environment, { hmr: { logger: false, }, diff --git a/packages/vite/src/node/ssr/runtime/serverHmrConnector.ts b/packages/vite/src/node/ssr/runtime/serverHmrConnector.ts index 282da14eeca4bc..5a4000794ba15a 100644 --- a/packages/vite/src/node/ssr/runtime/serverHmrConnector.ts +++ b/packages/vite/src/node/ssr/runtime/serverHmrConnector.ts @@ -1,12 +1,12 @@ -import type { CustomPayload, HMRPayload } from 'types/hmrPayload' +import type { CustomPayload, HotPayload } from 'types/hotPayload' import type { ModuleRunnerHMRConnection } from 'vite/module-runner' -import type { HMRBroadcasterClient, ServerHMRChannel } from '../../server/hmr' +import type { HotChannelClient, ServerHotChannel } from '../../server/hmr' -class ServerHMRBroadcasterClient implements HMRBroadcasterClient { - constructor(private readonly hmrChannel: ServerHMRChannel) {} +class ServerHMRBroadcasterClient implements HotChannelClient { + constructor(private readonly hotChannel: ServerHotChannel) {} send(...args: any[]) { - let payload: HMRPayload + let payload: HotPayload if (typeof args[0] === 'string') { payload = { type: 'custom', @@ -21,7 +21,7 @@ class ServerHMRBroadcasterClient implements HMRBroadcasterClient { 'Cannot send non-custom events from the client to the server.', ) } - this.hmrChannel.send(payload) + this.hotChannel.send(payload) } } @@ -30,17 +30,17 @@ class ServerHMRBroadcasterClient implements HMRBroadcasterClient { * @experimental */ export class ServerHMRConnector implements ModuleRunnerHMRConnection { - private handlers: ((payload: HMRPayload) => void)[] = [] + private handlers: ((payload: HotPayload) => void)[] = [] private hmrClient: ServerHMRBroadcasterClient private connected = false - constructor(private hmrChannel: ServerHMRChannel) { - this.hmrClient = new ServerHMRBroadcasterClient(hmrChannel) - hmrChannel.api.outsideEmitter.on('send', (payload: HMRPayload) => { + constructor(private hotChannel: ServerHotChannel) { + this.hmrClient = new ServerHMRBroadcasterClient(hotChannel) + hotChannel.api.outsideEmitter.on('send', (payload: HotPayload) => { this.handlers.forEach((listener) => listener(payload)) }) - this.hmrChannel = hmrChannel + this.hotChannel = hotChannel } isReady(): boolean { @@ -49,14 +49,14 @@ export class ServerHMRConnector implements ModuleRunnerHMRConnection { send(message: string): void { const payload = JSON.parse(message) as CustomPayload - this.hmrChannel.api.innerEmitter.emit( + this.hotChannel.api.innerEmitter.emit( payload.event, payload.data, this.hmrClient, ) } - onUpdate(handler: (payload: HMRPayload) => void): void { + onUpdate(handler: (payload: HotPayload) => void): void { this.handlers.push(handler) handler({ type: 'connected' }) this.connected = true diff --git a/packages/vite/src/node/ssr/runtime/serverModuleRunner.ts b/packages/vite/src/node/ssr/runtime/serverModuleRunner.ts index f24009ad4fd7be..2df093ead35fa7 100644 --- a/packages/vite/src/node/ssr/runtime/serverModuleRunner.ts +++ b/packages/vite/src/node/ssr/runtime/serverModuleRunner.ts @@ -7,7 +7,7 @@ import type { ModuleRunnerOptions, } from 'vite/module-runner' import type { DevEnvironment } from '../../server/environment' -import type { ServerHMRChannel } from '../../server/hmr' +import type { ServerHotChannel } from '../../server/hmr' import { ServerHMRConnector } from './serverHmrConnector' /** @@ -47,7 +47,7 @@ function createHMROptions( } } if (!('api' in environment.hot)) return false - const connection = new ServerHMRConnector(environment.hot as ServerHMRChannel) + const connection = new ServerHMRConnector(environment.hot as ServerHotChannel) return { connection, logger: options.hmr?.logger, diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index ee4f727158f60e..919d1054b5d9b2 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -1,4 +1,4 @@ -import type { Update } from 'types/hmrPayload' +import type { Update } from 'types/hotPayload' import type { ModuleNamespace, ViteHotContext } from 'types/hot' import type { InferCustomEventPayload } from 'types/customEvent' diff --git a/packages/vite/types/customEvent.d.ts b/packages/vite/types/customEvent.d.ts index b816a4c6c22907..e9d943aab32f64 100644 --- a/packages/vite/types/customEvent.d.ts +++ b/packages/vite/types/customEvent.d.ts @@ -3,7 +3,7 @@ import type { FullReloadPayload, PrunePayload, UpdatePayload, -} from './hmrPayload' +} from './hotPayload' export interface CustomEventMap { 'vite:beforeUpdate': UpdatePayload diff --git a/packages/vite/types/hmrPayload.d.ts b/packages/vite/types/hotPayload.d.ts similarity index 91% rename from packages/vite/types/hmrPayload.d.ts rename to packages/vite/types/hotPayload.d.ts index 2c6a9d0c2d1121..7c7f81f6cc1daa 100644 --- a/packages/vite/types/hmrPayload.d.ts +++ b/packages/vite/types/hotPayload.d.ts @@ -1,4 +1,6 @@ -export type HMRPayload = +/** @deprecated use HotPayload */ +export type HMRPayload = HotPayload +export type HotPayload = | ConnectedPayload | UpdatePayload | FullReloadPayload diff --git a/playground/hmr-ssr/vite.config.ts b/playground/hmr-ssr/vite.config.ts index 2d570d79acf8c4..f03eac818eee1b 100644 --- a/playground/hmr-ssr/vite.config.ts +++ b/playground/hmr-ssr/vite.config.ts @@ -8,18 +8,21 @@ export default defineConfig({ plugins: [ { name: 'mock-custom', - async handleHotUpdate({ file, read, server }) { + async hotUpdate({ environment, file, read, server }) { if (file.endsWith('customFile.js')) { const content = await read() const msg = content.match(/export const msg = '(\w+)'/)[1] - server.hot.send('custom:foo', { msg }) - server.hot.send('custom:remove', { msg }) + environment.hot.send('custom:foo', { msg }) + environment.hot.send('custom:remove', { msg }) } }, configureServer(server) { - server.hot.on('custom:remote-add', ({ a, b }, client) => { - client.send('custom:remote-add-result', { result: a + b }) - }) + server.environments.ssr.hot.on( + 'custom:remote-add', + ({ a, b }, client) => { + client.send('custom:remote-add-result', { result: a + b }) + }, + ) }, }, virtualPlugin(), @@ -45,7 +48,7 @@ export const virtual = _virtual + '${num}';` } }, configureServer(server) { - server.hot.on('virtual:increment', async () => { + server.environments.ssr.hot.on('virtual:increment', async () => { const mod = await server.environments.ssr.moduleGraph.getModuleByUrl( '\0virtual:file', diff --git a/playground/hmr/vite.config.ts b/playground/hmr/vite.config.ts index 1e3507e0e0f998..64d47797a841cd 100644 --- a/playground/hmr/vite.config.ts +++ b/playground/hmr/vite.config.ts @@ -10,18 +10,21 @@ export default defineConfig({ plugins: [ { name: 'mock-custom', - async handleHotUpdate({ file, read, server }) { + async hotUpdate({ environment, file, read }) { if (file.endsWith('customFile.js')) { const content = await read() const msg = content.match(/export const msg = '(\w+)'/)[1] - server.hot.send('custom:foo', { msg }) - server.hot.send('custom:remove', { msg }) + environment.hot.send('custom:foo', { msg }) + environment.hot.send('custom:remove', { msg }) } }, configureServer(server) { - server.hot.on('custom:remote-add', ({ a, b }, client) => { - client.send('custom:remote-add-result', { result: a + b }) - }) + server.environments.client.hot.on( + 'custom:remote-add', + ({ a, b }, client) => { + client.send('custom:remote-add-result', { result: a + b }) + }, + ) }, }, virtualPlugin(), @@ -47,7 +50,7 @@ export const virtual = _virtual + '${num}';` } }, configureServer(server) { - server.hot.on('virtual:increment', async () => { + server.environments.client.hot.on('virtual:increment', async () => { const mod = await server.environments.client.moduleGraph.getModuleByUrl( '\0virtual:file', diff --git a/playground/html/__tests__/html.spec.ts b/playground/html/__tests__/html.spec.ts index 3574412b49a485..896267ea06bae5 100644 --- a/playground/html/__tests__/html.spec.ts +++ b/playground/html/__tests__/html.spec.ts @@ -282,7 +282,7 @@ describe.runIf(isServe)('invalid', () => { await page.keyboard.press('Escape') await hiddenPromise - viteServer.hot.send({ + viteServer.environments.client.hot.send({ type: 'error', err: { message: 'someError',