From 0e18380f79d58a9478ee9b3658b3ea40dd9d3c61 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 13:31:00 +0100 Subject: [PATCH 1/8] refactor(hmr): keep buffer implementation internal, expose queueUpdate --- packages/vite/src/client/client.ts | 103 +++++++++++------------------ packages/vite/src/shared/hmr.ts | 44 ++++++++++-- 2 files changed, 76 insertions(+), 71 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 0d3f032dfea0fc..de8c172a6be52b 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -30,7 +30,6 @@ const socketHost = `${__HMR_HOSTNAME__ || importMetaUrl.hostname}:${ }${__HMR_BASE__}` const directSocketHost = __HMR_DIRECT_TARGET__ const base = __BASE__ || '/' -const messageBuffer: string[] = [] let socket: WebSocket try { @@ -134,38 +133,48 @@ const debounceReload = (time: number) => { } const pageReload = debounceReload(50) -const hmrClient = new HMRClient(console, async function importUpdatedModule({ - acceptedPath, - timestamp, - explicitImportRequired, - isWithinCircularImport, -}) { - const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`) - const importPromise = import( - /* @vite-ignore */ - base + - acceptedPathWithoutQuery.slice(1) + - `?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${ - query ? `&${query}` : '' - }` - ) - if (isWithinCircularImport) { - importPromise.catch(() => { - console.info( - `[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. ` + - `To debug and break the circular import, you can run \`vite --debug hmr\` to log the circular dependency path if a file change triggered it.`, - ) - pageReload() - }) - } - return await importPromise -}) +const hmrClient = new HMRClient( + console, + { + sendBuffer(buffer) { + if (socket.readyState === 1) { + buffer.forEach((msg) => socket.send(msg)) + } + }, + }, + async function importUpdatedModule({ + acceptedPath, + timestamp, + explicitImportRequired, + isWithinCircularImport, + }) { + const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`) + const importPromise = import( + /* @vite-ignore */ + base + + acceptedPathWithoutQuery.slice(1) + + `?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${ + query ? `&${query}` : '' + }` + ) + if (isWithinCircularImport) { + importPromise.catch(() => { + console.info( + `[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. ` + + `To debug and break the circular import, you can run \`vite --debug hmr\` to log the circular dependency path if a file change triggered it.`, + ) + pageReload() + }) + } + return await importPromise + }, +) async function handleMessage(payload: HMRPayload) { switch (payload.type) { case 'connected': console.debug(`[vite] connected.`) - sendMessageBuffer() + hmrClient.sendBuffer() // proxy(nginx, docker) hmr ws maybe caused timeout, // so send ping package let ws keep alive. setInterval(() => { @@ -190,7 +199,7 @@ async function handleMessage(payload: HMRPayload) { await Promise.all( payload.updates.map(async (update): Promise => { if (update.type === 'js-update') { - return queueUpdate(hmrClient.fetchUpdate(update)) + return hmrClient.queueUpdate(update) } // css-update @@ -306,26 +315,6 @@ function hasErrorOverlay() { return document.querySelectorAll(overlayId).length } -let pending = false -let queued: Promise<(() => void) | undefined>[] = [] - -/** - * buffer multiple hot updates triggered by the same src change - * so that they are invoked in the same order they were sent. - * (otherwise the order may be inconsistent because of the http request round trip) - */ -async function queueUpdate(p: Promise<(() => void) | undefined>) { - queued.push(p) - if (!pending) { - pending = true - await Promise.resolve() - pending = false - const loading = [...queued] - queued = [] - ;(await Promise.all(loading)).forEach((fn) => fn && fn()) - } -} - async function waitForSuccessfulPing( socketProtocol: string, hostAndPath: string, @@ -435,22 +424,8 @@ export function removeStyle(id: string): void { } } -function sendMessageBuffer() { - if (socket.readyState === 1) { - messageBuffer.forEach((msg) => socket.send(msg)) - messageBuffer.length = 0 - } -} - export function createHotContext(ownerPath: string): ViteHotContext { - return new HMRContext(ownerPath, hmrClient, { - addBuffer(message) { - messageBuffer.push(message) - }, - send() { - sendMessageBuffer() - }, - }) + return new HMRContext(hmrClient, ownerPath) } /** diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 9c0004793d30c3..0eb2601a893477 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -15,18 +15,16 @@ interface HotCallback { fn: (modules: Array) => void } -interface Connection { - addBuffer(message: string): void - send(): unknown +interface HMRConnection { + sendBuffer(message: string[]): void } export class HMRContext implements ViteHotContext { private newListeners: CustomListenersMap constructor( - private ownerPath: string, private hmrClient: HMRClient, - private connection: Connection, + private ownerPath: string, ) { if (!hmrClient.dataMap.has(ownerPath)) { hmrClient.dataMap.set(ownerPath, {}) @@ -141,8 +139,8 @@ export class HMRContext implements ViteHotContext { } send(event: T, data?: InferCustomEventPayload): void { - this.connection.addBuffer(JSON.stringify({ type: 'custom', event, data })) - this.connection.send() + this.hmrClient.addBuffer(JSON.stringify({ type: 'custom', event, data })) + this.hmrClient.sendBuffer() } private acceptDeps( @@ -169,8 +167,11 @@ export class HMRClient { public customListenersMap: CustomListenersMap = new Map() public ctxToListenersMap = new Map() + private buffer: string[] = [] + constructor( public logger: Console, + private connection: HMRConnection, // this allows up to implement reloading via different methods depending on the environment private importUpdatedModule: (update: Update) => Promise, ) {} @@ -199,6 +200,15 @@ export class HMRClient { }) } + public addBuffer(message: string): void { + this.buffer.push(message) + } + + public sendBuffer(): void { + this.connection.sendBuffer(this.buffer) + this.buffer = [] + } + protected warnFailedUpdate(err: Error, path: string | string[]): void { if (!err.message.includes('fetch')) { this.logger.error(err) @@ -210,6 +220,26 @@ export class HMRClient { ) } + private queued: Promise<(() => void) | undefined>[] = [] + private pendingQueue = false + + /** + * buffer multiple hot updates triggered by the same src change + * so that they are invoked in the same order they were sent. + * (otherwise the order may be inconsistent because of the http request round trip) + */ + public async queueUpdate(payload: Update): Promise { + this.queued.push(this.fetchUpdate(payload)) + if (!this.pendingQueue) { + this.pendingQueue = true + await Promise.resolve() + this.pendingQueue = false + const loading = [...this.queued] + this.queued = [] + ;(await Promise.all(loading)).forEach((fn) => fn && fn()) + } + } + public async fetchUpdate(update: Update): Promise<(() => void) | undefined> { const { path, acceptedPath } = update const mod = this.hotModulesMap.get(path) From 77edd70addf3fea4ef2adcbaa40e60e07c780a43 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 13:36:31 +0100 Subject: [PATCH 2/8] chore: cleanup --- packages/vite/src/client/client.ts | 17 +++++++---------- packages/vite/src/shared/hmr.ts | 14 +++++++------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index de8c172a6be52b..15c6c4f2b6e30f 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -133,16 +133,13 @@ const debounceReload = (time: number) => { } const pageReload = debounceReload(50) -const hmrClient = new HMRClient( - console, - { - sendBuffer(buffer) { - if (socket.readyState === 1) { - buffer.forEach((msg) => socket.send(msg)) - } - }, +const hmrClient = new HMRClient(console, { + sendBufferedMessage(messages) { + if (socket.readyState === 1) { + messages.forEach((msg) => socket.send(msg)) + } }, - async function importUpdatedModule({ + async importUpdatedModule({ acceptedPath, timestamp, explicitImportRequired, @@ -168,7 +165,7 @@ const hmrClient = new HMRClient( } return await importPromise }, -) +}) async function handleMessage(payload: HMRPayload) { switch (payload.type) { diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 0eb2601a893477..6bc3691816fd75 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -15,8 +15,10 @@ interface HotCallback { fn: (modules: Array) => void } -interface HMRConnection { - sendBuffer(message: string[]): void +interface HMRClientOptions { + sendBufferedMessage(message: string[]): void + // this allows implementing reloading via different methods depending on the environment + importUpdatedModule(update: Update): Promise } export class HMRContext implements ViteHotContext { @@ -171,9 +173,7 @@ export class HMRClient { constructor( public logger: Console, - private connection: HMRConnection, - // this allows up to implement reloading via different methods depending on the environment - private importUpdatedModule: (update: Update) => Promise, + private options: HMRClientOptions, ) {} public async notifyListeners( @@ -205,7 +205,7 @@ export class HMRClient { } public sendBuffer(): void { - this.connection.sendBuffer(this.buffer) + this.options.sendBufferedMessage(this.buffer) this.buffer = [] } @@ -262,7 +262,7 @@ export class HMRClient { const disposer = this.disposeMap.get(acceptedPath) if (disposer) await disposer(this.dataMap.get(acceptedPath)) try { - fetchedModule = await this.importUpdatedModule(update) + fetchedModule = await this.options.importUpdatedModule(update) } catch (e) { this.warnFailedUpdate(e, acceptedPath) } From 7c45bb382385e3a139cba0d466c131b005333cda Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 13:49:31 +0100 Subject: [PATCH 3/8] refactor: renaming --- packages/vite/src/client/client.ts | 2 +- packages/vite/src/shared/hmr.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 15c6c4f2b6e30f..9270d3e5cd573c 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -134,7 +134,7 @@ const debounceReload = (time: number) => { const pageReload = debounceReload(50) const hmrClient = new HMRClient(console, { - sendBufferedMessage(messages) { + sendCustomMessages(messages) { if (socket.readyState === 1) { messages.forEach((msg) => socket.send(msg)) } diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 6bc3691816fd75..d4a87ca030df75 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -16,7 +16,7 @@ interface HotCallback { } interface HMRClientOptions { - sendBufferedMessage(message: string[]): void + sendCustomMessages(message: string[]): void // this allows implementing reloading via different methods depending on the environment importUpdatedModule(update: Update): Promise } @@ -205,7 +205,7 @@ export class HMRClient { } public sendBuffer(): void { - this.options.sendBufferedMessage(this.buffer) + this.options.sendCustomMessages(this.buffer) this.buffer = [] } From 07742a10f86611f138daa810ad14eb2c096cd7c4 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 13:51:54 +0100 Subject: [PATCH 4/8] fix: correctly empty buffer only if successful --- packages/vite/src/client/client.ts | 2 ++ packages/vite/src/shared/hmr.ts | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 9270d3e5cd573c..aebccef830f7d8 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -137,7 +137,9 @@ const hmrClient = new HMRClient(console, { sendCustomMessages(messages) { if (socket.readyState === 1) { messages.forEach((msg) => socket.send(msg)) + return true } + return false }, async importUpdatedModule({ acceptedPath, diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index d4a87ca030df75..6a2fd29264828f 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -16,8 +16,17 @@ interface HotCallback { } interface HMRClientOptions { - sendCustomMessages(message: string[]): void - // this allows implementing reloading via different methods depending on the environment + /** + * Send buffered messages to the client. + * + * Should return `true` if messages are sent successfully. + */ + sendCustomMessages(messages: string[]): boolean + /** + * Execute the update. + * + * This allows implementing reloading via different methods depending on the environment + */ importUpdatedModule(update: Update): Promise } @@ -205,8 +214,10 @@ export class HMRClient { } public sendBuffer(): void { - this.options.sendCustomMessages(this.buffer) - this.buffer = [] + const clearBuffer = this.options.sendCustomMessages(this.buffer) + if (clearBuffer) { + this.buffer.length = 0 + } } protected warnFailedUpdate(err: Error, path: string | string[]): void { From 36f1e575c296a3d3f02b35d175928e338d72cbd0 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 13:58:39 +0100 Subject: [PATCH 5/8] refactor: cleanup --- packages/vite/src/client/client.ts | 18 ++++++++---------- packages/vite/src/shared/hmr.ts | 30 ++++++++++++++---------------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index aebccef830f7d8..d1a1e584b6edb9 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -133,15 +133,13 @@ const debounceReload = (time: number) => { } const pageReload = debounceReload(50) -const hmrClient = new HMRClient(console, { - sendCustomMessages(messages) { - if (socket.readyState === 1) { - messages.forEach((msg) => socket.send(msg)) - return true - } - return false +const hmrClient = new HMRClient( + console, + { + isReady: () => socket.readyState === 1, + send: (message) => socket.send(message), }, - async importUpdatedModule({ + async function importUpdatedModule({ acceptedPath, timestamp, explicitImportRequired, @@ -167,13 +165,13 @@ const hmrClient = new HMRClient(console, { } return await importPromise }, -}) +) async function handleMessage(payload: HMRPayload) { switch (payload.type) { case 'connected': console.debug(`[vite] connected.`) - hmrClient.sendBuffer() + hmrClient.sendCustomMessages() // proxy(nginx, docker) hmr ws maybe caused timeout, // so send ping package let ws keep alive. setInterval(() => { diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 6a2fd29264828f..8f2759415996e9 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -15,19 +15,15 @@ interface HotCallback { fn: (modules: Array) => void } -interface HMRClientOptions { +interface HMRConnection { /** - * Send buffered messages to the client. - * - * Should return `true` if messages are sent successfully. + * Checked before sending messages to the client. */ - sendCustomMessages(messages: string[]): boolean + isReady(): boolean /** - * Execute the update. - * - * This allows implementing reloading via different methods depending on the environment + * Send message to the client. */ - importUpdatedModule(update: Update): Promise + send(messages: string): void } export class HMRContext implements ViteHotContext { @@ -151,7 +147,7 @@ export class HMRContext implements ViteHotContext { send(event: T, data?: InferCustomEventPayload): void { this.hmrClient.addBuffer(JSON.stringify({ type: 'custom', event, data })) - this.hmrClient.sendBuffer() + this.hmrClient.sendCustomMessages() } private acceptDeps( @@ -182,7 +178,9 @@ export class HMRClient { constructor( public logger: Console, - private options: HMRClientOptions, + private connection: HMRConnection, + // This allows implementing reloading via different methods depending on the environment + private importUpdatedModule: (update: Update) => Promise, ) {} public async notifyListeners( @@ -213,10 +211,10 @@ export class HMRClient { this.buffer.push(message) } - public sendBuffer(): void { - const clearBuffer = this.options.sendCustomMessages(this.buffer) - if (clearBuffer) { - this.buffer.length = 0 + public sendCustomMessages(): void { + if (this.connection.isReady()) { + this.buffer.forEach((msg) => this.connection.send(msg)) + this.buffer = [] } } @@ -273,7 +271,7 @@ export class HMRClient { const disposer = this.disposeMap.get(acceptedPath) if (disposer) await disposer(this.dataMap.get(acceptedPath)) try { - fetchedModule = await this.options.importUpdatedModule(update) + fetchedModule = await this.importUpdatedModule(update) } catch (e) { this.warnFailedUpdate(e, acceptedPath) } From 094d32515533db545c77ce74366ce61b28193f60 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 2 Jan 2024 14:01:13 +0100 Subject: [PATCH 6/8] chore: cleanup --- packages/vite/src/client/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index d1a1e584b6edb9..12b6cccde40ee8 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -136,7 +136,7 @@ const pageReload = debounceReload(50) const hmrClient = new HMRClient( console, { - isReady: () => socket.readyState === 1, + isReady: () => socket && socket.readyState === 1, send: (message) => socket.send(message), }, async function importUpdatedModule({ From 1395039043a9b74e068f34849478af4bf70c7989 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Mon, 8 Jan 2024 17:52:20 +0100 Subject: [PATCH 7/8] refactor: renaming --- packages/vite/src/client/client.ts | 2 +- packages/vite/src/shared/hmr.ts | 32 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 12b6cccde40ee8..dfb67284c89b30 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -171,7 +171,7 @@ async function handleMessage(payload: HMRPayload) { switch (payload.type) { case 'connected': console.debug(`[vite] connected.`) - hmrClient.sendCustomMessages() + hmrClient.flushMessageQueue() // proxy(nginx, docker) hmr ws maybe caused timeout, // so send ping package let ws keep alive. setInterval(() => { diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 8f2759415996e9..4748441f6852d9 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -146,8 +146,7 @@ export class HMRContext implements ViteHotContext { } send(event: T, data?: InferCustomEventPayload): void { - this.hmrClient.addBuffer(JSON.stringify({ type: 'custom', event, data })) - this.hmrClient.sendCustomMessages() + this.hmrClient.sendMessage(JSON.stringify({ type: 'custom', event, data })) } private acceptDeps( @@ -174,7 +173,7 @@ export class HMRClient { public customListenersMap: CustomListenersMap = new Map() public ctxToListenersMap = new Map() - private buffer: string[] = [] + private messageQueue: string[] = [] constructor( public logger: Console, @@ -207,14 +206,15 @@ export class HMRClient { }) } - public addBuffer(message: string): void { - this.buffer.push(message) + public sendMessage(message: string): void { + this.messageQueue.push(message) + this.flushMessageQueue() } - public sendCustomMessages(): void { + public flushMessageQueue(): void { if (this.connection.isReady()) { - this.buffer.forEach((msg) => this.connection.send(msg)) - this.buffer = [] + this.messageQueue.forEach((msg) => this.connection.send(msg)) + this.messageQueue = [] } } @@ -229,8 +229,8 @@ export class HMRClient { ) } - private queued: Promise<(() => void) | undefined>[] = [] - private pendingQueue = false + private updateQueue: Promise<(() => void) | undefined>[] = [] + private pendingUpdateQueue = false /** * buffer multiple hot updates triggered by the same src change @@ -238,13 +238,13 @@ export class HMRClient { * (otherwise the order may be inconsistent because of the http request round trip) */ public async queueUpdate(payload: Update): Promise { - this.queued.push(this.fetchUpdate(payload)) - if (!this.pendingQueue) { - this.pendingQueue = true + this.updateQueue.push(this.fetchUpdate(payload)) + if (!this.pendingUpdateQueue) { + this.pendingUpdateQueue = true await Promise.resolve() - this.pendingQueue = false - const loading = [...this.queued] - this.queued = [] + this.pendingUpdateQueue = false + const loading = [...this.updateQueue] + this.updateQueue = [] ;(await Promise.all(loading)).forEach((fn) => fn && fn()) } } From a5618554b43b8e15da2ed54c47926d3860023fb6 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Mon, 8 Jan 2024 17:59:32 +0100 Subject: [PATCH 8/8] chore: add a separate class for messages --- packages/vite/src/client/client.ts | 2 +- packages/vite/src/shared/hmr.ts | 44 ++++++++++++++++++------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index dfb67284c89b30..aaea3300bf2619 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -171,7 +171,7 @@ async function handleMessage(payload: HMRPayload) { switch (payload.type) { case 'connected': console.debug(`[vite] connected.`) - hmrClient.flushMessageQueue() + hmrClient.messenger.flush() // proxy(nginx, docker) hmr ws maybe caused timeout, // so send ping package let ws keep alive. setInterval(() => { diff --git a/packages/vite/src/shared/hmr.ts b/packages/vite/src/shared/hmr.ts index 4748441f6852d9..9617ddb3a949a4 100644 --- a/packages/vite/src/shared/hmr.ts +++ b/packages/vite/src/shared/hmr.ts @@ -15,7 +15,7 @@ interface HotCallback { fn: (modules: Array) => void } -interface HMRConnection { +export interface HMRConnection { /** * Checked before sending messages to the client. */ @@ -146,7 +146,9 @@ export class HMRContext implements ViteHotContext { } send(event: T, data?: InferCustomEventPayload): void { - this.hmrClient.sendMessage(JSON.stringify({ type: 'custom', event, data })) + this.hmrClient.messenger.send( + JSON.stringify({ type: 'custom', event, data }), + ) } private acceptDeps( @@ -165,6 +167,24 @@ export class HMRContext implements ViteHotContext { } } +class HMRMessenger { + constructor(private connection: HMRConnection) {} + + private queue: string[] = [] + + public send(message: string): void { + this.queue.push(message) + this.flush() + } + + public flush(): void { + if (this.connection.isReady()) { + this.queue.forEach((msg) => this.connection.send(msg)) + this.queue = [] + } + } +} + export class HMRClient { public hotModulesMap = new Map() public disposeMap = new Map void | Promise>() @@ -173,14 +193,16 @@ export class HMRClient { public customListenersMap: CustomListenersMap = new Map() public ctxToListenersMap = new Map() - private messageQueue: string[] = [] + public messenger: HMRMessenger constructor( public logger: Console, - private connection: HMRConnection, + connection: HMRConnection, // This allows implementing reloading via different methods depending on the environment private importUpdatedModule: (update: Update) => Promise, - ) {} + ) { + this.messenger = new HMRMessenger(connection) + } public async notifyListeners( event: T, @@ -206,18 +228,6 @@ export class HMRClient { }) } - public sendMessage(message: string): void { - this.messageQueue.push(message) - this.flushMessageQueue() - } - - public flushMessageQueue(): void { - if (this.connection.isReady()) { - this.messageQueue.forEach((msg) => this.connection.send(msg)) - this.messageQueue = [] - } - } - protected warnFailedUpdate(err: Error, path: string | string[]): void { if (!err.message.includes('fetch')) { this.logger.error(err)