Skip to content

Commit 18a394c

Browse files
bgwsokra
authored andcommitted
chore(HMR clients): Clean up tryApplyUpdates, reduce differences between app/pages versions
1 parent 8a5f08e commit 18a394c

File tree

4 files changed

+82
-136
lines changed

4 files changed

+82
-136
lines changed

packages/next/src/client/components/react-dev-overlay/app/hot-reloader-client.tsx

+37-70
Original file line numberDiff line numberDiff line change
@@ -81,23 +81,6 @@ export function waitForWebpackRuntimeHotUpdate() {
8181
return pendingHotUpdateWebpack
8282
}
8383

84-
function handleSuccessfulHotUpdateWebpack(
85-
dispatcher: Dispatcher,
86-
sendMessage: (message: string) => void,
87-
updatedModules: ReadonlyArray<string>
88-
) {
89-
resolvePendingHotUpdateWebpack()
90-
dispatcher.onBuildOk()
91-
reportHmrLatency(
92-
sendMessage,
93-
updatedModules,
94-
webpackStartMsSinceEpoch!,
95-
Date.now()
96-
)
97-
98-
dispatcher.onRefresh()
99-
}
100-
10184
// There is a newer version of the code available.
10285
function handleAvailableHash(hash: string) {
10386
// Update last known compilation hash.
@@ -160,10 +143,8 @@ function performFullReload(err: any, sendMessage: any) {
160143
}
161144

162145
// Attempt to update code on the fly, fall back to a hard reload.
163-
function tryApplyUpdates(
164-
onBeforeUpdate: (hasUpdates: boolean) => void,
165-
onHotUpdateSuccess: (updatedModules: string[]) => void,
166-
sendMessage: any,
146+
function tryApplyUpdatesWebpack(
147+
sendMessage: (message: string) => void,
167148
dispatcher: Dispatcher
168149
) {
169150
if (!isUpdateAvailable() || !canApplyUpdates()) {
@@ -173,8 +154,11 @@ function tryApplyUpdates(
173154
return
174155
}
175156

176-
function handleApplyUpdates(err: any, updatedModules: string[] | null) {
177-
if (err || RuntimeErrorHandler.hadRuntimeError || !updatedModules) {
157+
function handleApplyUpdates(
158+
err: any,
159+
updatedModules: (string | number)[] | null
160+
) {
161+
if (err || RuntimeErrorHandler.hadRuntimeError || updatedModules == null) {
178162
if (err) {
179163
console.warn(REACT_REFRESH_FULL_RELOAD)
180164
} else if (RuntimeErrorHandler.hadRuntimeError) {
@@ -184,50 +168,50 @@ function tryApplyUpdates(
184168
return
185169
}
186170

187-
const hasUpdates = Boolean(updatedModules.length)
188-
if (typeof onHotUpdateSuccess === 'function') {
189-
// Maybe we want to do something.
190-
onHotUpdateSuccess(updatedModules)
191-
}
171+
dispatcher.onBuildOk()
192172

193173
if (isUpdateAvailable()) {
194174
// While we were updating, there was a new update! Do it again.
195-
tryApplyUpdates(
196-
hasUpdates ? () => {} : onBeforeUpdate,
197-
hasUpdates ? () => dispatcher.onBuildOk() : onHotUpdateSuccess,
198-
sendMessage,
199-
dispatcher
200-
)
201-
} else {
202-
dispatcher.onBuildOk()
203-
if (process.env.__NEXT_TEST_MODE) {
204-
afterApplyUpdates(() => {
205-
if (self.__NEXT_HMR_CB) {
206-
self.__NEXT_HMR_CB()
207-
self.__NEXT_HMR_CB = null
208-
}
209-
})
210-
}
175+
tryApplyUpdatesWebpack(sendMessage, dispatcher)
176+
return
177+
}
178+
179+
dispatcher.onRefresh()
180+
resolvePendingHotUpdateWebpack()
181+
reportHmrLatency(
182+
sendMessage,
183+
updatedModules,
184+
webpackStartMsSinceEpoch!,
185+
Date.now()
186+
)
187+
188+
if (process.env.__NEXT_TEST_MODE) {
189+
afterApplyUpdates(() => {
190+
if (self.__NEXT_HMR_CB) {
191+
self.__NEXT_HMR_CB()
192+
self.__NEXT_HMR_CB = null
193+
}
194+
})
211195
}
212196
}
213197

214198
// https://webpack.js.org/api/hot-module-replacement/#check
215199
module.hot
216200
.check(/* autoApply */ false)
217-
.then((updatedModules: any[] | null) => {
218-
if (!updatedModules) {
201+
.then((updatedModules: (string | number)[] | null) => {
202+
if (updatedModules == null) {
219203
return null
220204
}
221205

222-
if (typeof onBeforeUpdate === 'function') {
223-
const hasUpdates = Boolean(updatedModules.length)
224-
onBeforeUpdate(hasUpdates)
225-
}
206+
// We should always handle an update, even if updatedModules is empty (but
207+
// non-null) for any reason. That's what webpack would normally do:
208+
// https://github.com/webpack/webpack/blob/3aa6b6bc3a64/lib/hmr/HotModuleReplacement.runtime.js#L296-L298
209+
dispatcher.onBeforeRefresh()
226210
// https://webpack.js.org/api/hot-module-replacement/#apply
227211
return module.hot.apply()
228212
})
229213
.then(
230-
(updatedModules: any[] | null) => {
214+
(updatedModules: (string | number)[] | null) => {
231215
handleApplyUpdates(null, updatedModules)
232216
},
233217
(err: any) => {
@@ -236,7 +220,7 @@ function tryApplyUpdates(
236220
)
237221
}
238222

239-
/** Handles messages from the sevrer for the App Router. */
223+
/** Handles messages from the server for the App Router. */
240224
function processMessage(
241225
obj: HMR_ACTION_TYPES,
242226
sendMessage: (message: string) => void,
@@ -288,24 +272,7 @@ function processMessage(
288272
}
289273
dispatcher.onBuildOk()
290274
} else {
291-
tryApplyUpdates(
292-
function onBeforeHotUpdate(hasUpdates: boolean) {
293-
if (hasUpdates) {
294-
dispatcher.onBeforeRefresh()
295-
}
296-
},
297-
function onSuccessfulHotUpdate(webpackUpdatedModules: string[]) {
298-
// Only dismiss it when we're sure it's a hot update.
299-
// Otherwise it would flicker right before the reload.
300-
handleSuccessfulHotUpdateWebpack(
301-
dispatcher,
302-
sendMessage,
303-
webpackUpdatedModules
304-
)
305-
},
306-
sendMessage,
307-
dispatcher
308-
)
275+
tryApplyUpdatesWebpack(sendMessage, dispatcher)
309276
}
310277
}
311278

packages/next/src/client/components/react-dev-overlay/pages/hot-reloader-client.ts

+43-64
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* SOFTWARE.
2525
*/
2626

27+
/// <reference types="webpack/module.d.ts" />
28+
2729
// This file is a modified version of the Create React App HMR dev client that
2830
// can be found here:
2931
// https://github.com/facebook/create-react-app/blob/v3.4.1/packages/react-dev-utils/webpackHotDevClient.js
@@ -55,10 +57,8 @@ import {
5557
} from '../shared'
5658
import { RuntimeErrorHandler } from '../../errors/runtime-error-handler'
5759
import reportHmrLatency from '../utils/report-hmr-latency'
58-
import {
59-
extractModulesFromTurbopackMessage,
60-
TurbopackHmr,
61-
} from '../utils/turbopack-hot-reloader-common'
60+
import { TurbopackHmr } from '../utils/turbopack-hot-reloader-common'
61+
6262
// This alternative WebpackDevServer combines the functionality of:
6363
// https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
6464
// https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
@@ -149,7 +149,7 @@ function handleSuccess() {
149149

150150
// Attempt to apply hot updates or reload.
151151
if (isHotUpdate) {
152-
tryApplyUpdates(onBeforeFastRefresh, onFastRefresh)
152+
tryApplyUpdatesWebpack()
153153
}
154154
}
155155

@@ -189,7 +189,7 @@ function handleWarnings(warnings: any) {
189189

190190
// Attempt to apply hot updates or reload.
191191
if (isHotUpdate) {
192-
tryApplyUpdates(onBeforeFastRefresh, onFastRefresh)
192+
tryApplyUpdatesWebpack()
193193
}
194194
}
195195

@@ -233,30 +233,6 @@ const turbopackHmr: TurbopackHmr | null = process.env.TURBOPACK
233233
: null
234234
let isrManifest: Record<string, boolean> = {}
235235

236-
function onBeforeFastRefresh(updatedModules: string[]) {
237-
if (updatedModules.length > 0) {
238-
// Only trigger a pending state if we have updates to apply
239-
// (cf. onFastRefresh)
240-
onBeforeRefresh()
241-
}
242-
}
243-
244-
function onFastRefresh(updatedModules: ReadonlyArray<string> = []) {
245-
onBuildOk()
246-
if (updatedModules.length === 0) {
247-
return
248-
}
249-
250-
onRefresh()
251-
252-
reportHmrLatency(
253-
sendMessage,
254-
updatedModules,
255-
webpackStartMsSinceEpoch!,
256-
Date.now()
257-
)
258-
}
259-
260236
// There is a newer version of the code available.
261237
function handleAvailableHash(hash: string) {
262238
// Update last known compilation hash.
@@ -282,7 +258,7 @@ export function handleStaticIndicator() {
282258
}
283259
}
284260

285-
/** Handles messages from the sevrer for the Pages Router. */
261+
/** Handles messages from the server for the Pages Router. */
286262
function processMessage(obj: HMR_ACTION_TYPES) {
287263
if (!('action' in obj)) {
288264
return
@@ -325,6 +301,7 @@ function processMessage(obj: HMR_ACTION_TYPES) {
325301
return handleErrors(errors)
326302
}
327303

304+
// NOTE: Turbopack does not currently send warnings
328305
const hasWarnings = Boolean(warnings && warnings.length)
329306
if (hasWarnings) {
330307
sendMessage(
@@ -371,8 +348,7 @@ function processMessage(obj: HMR_ACTION_TYPES) {
371348
break
372349
}
373350
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE: {
374-
const updatedModules = extractModulesFromTurbopackMessage(obj.data)
375-
onBeforeFastRefresh([...updatedModules])
351+
onBeforeRefresh()
376352
for (const listener of turbopackMessageListeners) {
377353
listener({
378354
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
@@ -424,10 +400,7 @@ function afterApplyUpdates(fn: () => void) {
424400
}
425401

426402
// Attempt to update code on the fly, fall back to a hard reload.
427-
function tryApplyUpdates(
428-
onBeforeHotUpdate: ((updatedModules: string[]) => unknown) | undefined,
429-
onHotUpdateSuccess: (updatedModules: string[]) => unknown
430-
) {
403+
function tryApplyUpdatesWebpack() {
431404
if (!module.hot) {
432405
// HotModuleReplacementPlugin is not in Webpack configuration.
433406
console.error('HotModuleReplacementPlugin is not in Webpack configuration.')
@@ -440,8 +413,11 @@ function tryApplyUpdates(
440413
return
441414
}
442415

443-
function handleApplyUpdates(err: any, updatedModules: string[] | null) {
444-
if (err || RuntimeErrorHandler.hadRuntimeError || !updatedModules) {
416+
function handleApplyUpdates(
417+
err: any,
418+
updatedModules: (string | number)[] | null
419+
) {
420+
if (err || RuntimeErrorHandler.hadRuntimeError || updatedModules == null) {
445421
if (err) {
446422
console.warn(REACT_REFRESH_FULL_RELOAD)
447423
} else if (RuntimeErrorHandler.hadRuntimeError) {
@@ -451,46 +427,49 @@ function tryApplyUpdates(
451427
return
452428
}
453429

454-
if (typeof onHotUpdateSuccess === 'function') {
455-
// Maybe we want to do something.
456-
onHotUpdateSuccess(updatedModules)
457-
}
430+
onBuildOk()
458431

459432
if (isUpdateAvailable()) {
460433
// While we were updating, there was a new update! Do it again.
461-
// However, this time, don't trigger a pending refresh state.
462-
tryApplyUpdates(
463-
updatedModules.length > 0 ? undefined : onBeforeHotUpdate,
464-
updatedModules.length > 0 ? onBuildOk : onHotUpdateSuccess
465-
)
466-
} else {
467-
onBuildOk()
468-
if (process.env.__NEXT_TEST_MODE) {
469-
afterApplyUpdates(() => {
470-
if (self.__NEXT_HMR_CB) {
471-
self.__NEXT_HMR_CB()
472-
self.__NEXT_HMR_CB = null
473-
}
474-
})
475-
}
434+
tryApplyUpdatesWebpack()
435+
return
436+
}
437+
438+
onRefresh()
439+
reportHmrLatency(
440+
sendMessage,
441+
updatedModules,
442+
webpackStartMsSinceEpoch!,
443+
Date.now()
444+
)
445+
446+
if (process.env.__NEXT_TEST_MODE) {
447+
afterApplyUpdates(() => {
448+
if (self.__NEXT_HMR_CB) {
449+
self.__NEXT_HMR_CB()
450+
self.__NEXT_HMR_CB = null
451+
}
452+
})
476453
}
477454
}
478455

479456
// https://webpack.js.org/api/hot-module-replacement/#check
480457
module.hot
481458
.check(/* autoApply */ false)
482-
.then((updatedModules: any) => {
483-
if (!updatedModules) {
459+
.then((updatedModules: (string | number)[] | null) => {
460+
if (updatedModules == null) {
484461
return null
485462
}
486463

487-
if (typeof onBeforeHotUpdate === 'function') {
488-
onBeforeHotUpdate(updatedModules)
489-
}
464+
// We should always handle an update, even if updatedModules is empty (but
465+
// non-null) for any reason. That's what webpack would normally do:
466+
// https://github.com/webpack/webpack/blob/3aa6b6bc3a64/lib/hmr/HotModuleReplacement.runtime.js#L296-L298
467+
onBeforeRefresh()
468+
// https://webpack.js.org/api/hot-module-replacement/#apply
490469
return module.hot.apply()
491470
})
492471
.then(
493-
(updatedModules: any) => {
472+
(updatedModules: (string | number)[] | null) => {
494473
handleApplyUpdates(null, updatedModules)
495474
},
496475
(err: any) => {

packages/next/src/client/components/react-dev-overlay/utils/report-hmr-latency.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ declare global {
66

77
export default function reportHmrLatency(
88
sendMessage: (message: string) => void,
9-
updatedModules: ReadonlyArray<string>,
9+
updatedModules: ReadonlyArray<string | number>,
1010
startMsSinceEpoch: number,
1111
endMsSinceEpoch: number
1212
) {

packages/next/src/client/components/react-dev-overlay/utils/turbopack-hot-reloader-common.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class TurbopackHmr {
4848
}
4949
}
5050

51-
export function extractModulesFromTurbopackMessage(
51+
function extractModulesFromTurbopackMessage(
5252
data: TurbopackUpdate | TurbopackUpdate[]
5353
): Set<string> {
5454
const updatedModules: Set<string> = new Set()

0 commit comments

Comments
 (0)