Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bcd2721

Browse files
committed
WIP fix(turbopack): Suppress logging for short no-op turbopack HMRs
1 parent 4b56b12 commit bcd2721

File tree

3 files changed

+88
-28
lines changed

3 files changed

+88
-28
lines changed

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,16 @@ function processMessage(
289289
function handleHotUpdate() {
290290
if (process.env.TURBOPACK) {
291291
const built = turbopackHmr!.onBuilt()
292-
dispatcher.onBuildOk()
293-
reportHmrLatency(
294-
sendMessage,
295-
[...built.updatedModules],
296-
built.startMsSinceEpoch,
297-
built.endMsSinceEpoch
298-
)
292+
if (built?.hasUpdates) {
293+
dispatcher.onBuildOk()
294+
dispatcher.onBeforeRefresh()
295+
reportHmrLatency(
296+
sendMessage,
297+
[...built.updatedModules],
298+
built.startMsSinceEpoch,
299+
built.endMsSinceEpoch
300+
)
301+
}
299302
} else {
300303
tryApplyUpdates(
301304
function onBeforeHotUpdate(hasUpdates: boolean) {
@@ -343,8 +346,8 @@ function processMessage(
343346
} else {
344347
webpackStartMsSinceEpoch = Date.now()
345348
setPendingHotUpdateWebpack()
349+
console.log('[Fast Refresh] rebuilding')
346350
}
347-
console.log('[Fast Refresh] rebuilding')
348351
break
349352
}
350353
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:
@@ -427,7 +430,6 @@ function processMessage(
427430
break
428431
}
429432
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE: {
430-
dispatcher.onBeforeRefresh()
431433
processTurbopackMessage({
432434
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
433435
data: obj.data,

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ import {
5353
} from '../shared'
5454
import { RuntimeErrorHandler } from '../../errors/runtime-error-handler'
5555
import reportHmrLatency from '../utils/report-hmr-latency'
56-
import {
57-
extractModulesFromTurbopackMessage,
58-
TurbopackHmr,
59-
} from '../utils/turbopack-hot-reloader-common'
56+
import { TurbopackHmr } from '../utils/turbopack-hot-reloader-common'
6057
// This alternative WebpackDevServer combines the functionality of:
6158
// https://github.com/webpack/webpack-dev-server/blob/webpack-1/client/index.js
6259
// https://github.com/webpack/webpack/blob/webpack-1/hot/dev-server.js
@@ -131,13 +128,15 @@ function handleSuccess() {
131128

132129
if (process.env.TURBOPACK) {
133130
const built = turbopackHmr!.onBuilt()
134-
reportHmrLatency(
135-
sendMessage,
136-
[...built.updatedModules],
137-
built.startMsSinceEpoch,
138-
built.endMsSinceEpoch
139-
)
140-
onBuildOk()
131+
if (built?.hasUpdates) {
132+
reportHmrLatency(
133+
sendMessage,
134+
[...built.updatedModules],
135+
built.startMsSinceEpoch,
136+
built.endMsSinceEpoch
137+
)
138+
onBuildOk()
139+
}
141140
} else {
142141
const isHotUpdate =
143142
!isFirstCompilation ||
@@ -295,8 +294,8 @@ function processMessage(obj: HMR_ACTION_TYPES) {
295294
turbopackHmr!.onBuilding()
296295
} else {
297296
webpackStartMsSinceEpoch = Date.now()
297+
console.log('[Fast Refresh] rebuilding')
298298
}
299-
console.log('[Fast Refresh] rebuilding')
300299
break
301300
}
302301
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:
@@ -367,8 +366,6 @@ function processMessage(obj: HMR_ACTION_TYPES) {
367366
break
368367
}
369368
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE: {
370-
const updatedModules = extractModulesFromTurbopackMessage(obj.data)
371-
onBeforeFastRefresh([...updatedModules])
372369
for (const listener of turbopackMessageListeners) {
373370
listener({
374371
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,

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

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import type { TurbopackMessageAction } from '../../../../server/dev/hot-reloader-types'
22
import type { Update as TurbopackUpdate } from '../../../../build/swc/types'
33

4+
declare global {
5+
interface Window {
6+
__NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS: boolean | undefined
7+
}
8+
}
9+
10+
// How long to wait before reporting the HMR start, used to suppress irrelevant
11+
// `BUILDING` events. Does not impact reported latency.
12+
const TURBOPACK_HMR_START_DELAY_MS = 100
13+
414
interface Built {
15+
hasUpdates: boolean
516
updatedModules: Set<string>
617
startMsSinceEpoch: number
718
endMsSinceEpoch: number
@@ -11,39 +22,89 @@ export class TurbopackHmr {
1122
#updatedModules: Set<string>
1223
#startMsSinceEpoch: number | undefined
1324
#lastUpdateMsSinceEpoch: number | undefined
25+
#deferredReportHmrStartId: ReturnType<typeof setTimeout> | undefined
1426

1527
constructor() {
1628
this.#updatedModules = new Set()
1729
}
1830

31+
// HACK: Turbopack tends to generate a lot of irrelevant "BUILDING" actions,
32+
// as it reports *any* compilation, including fully no-op/cached compilations
33+
// and those unrelated to HMR. Fixing this would require significant
34+
// architectural changes.
35+
//
36+
// Work around this by deferring any "rebuilding" message by 100ms. If we get
37+
// a BUILT event within that threshold and nothing has changed, just suppress
38+
// the message entirely.
39+
#runDeferredReportHmrStart() {
40+
if (this.#deferredReportHmrStartId != null) {
41+
console.log('[Fast Refresh] rebuilding')
42+
this.#cancelDeferredReportHmrStart()
43+
}
44+
}
45+
46+
#cancelDeferredReportHmrStart() {
47+
clearTimeout(this.#deferredReportHmrStartId)
48+
this.#deferredReportHmrStartId = undefined
49+
}
50+
1951
onBuilding() {
2052
this.#lastUpdateMsSinceEpoch = undefined
53+
this.#cancelDeferredReportHmrStart()
2154
this.#startMsSinceEpoch = Date.now()
55+
56+
if (self.__NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS) {
57+
// debugging feature: don't defer/suppress noisy no-op HMR update messages
58+
this.#runDeferredReportHmrStart()
59+
} else {
60+
// report the HMR start after a short delay
61+
this.#deferredReportHmrStartId = setTimeout(
62+
() => this.#runDeferredReportHmrStart(),
63+
TURBOPACK_HMR_START_DELAY_MS
64+
)
65+
}
2266
}
2367

2468
onTurbopackMessage(msg: TurbopackMessageAction) {
69+
this.#runDeferredReportHmrStart()
2570
this.#lastUpdateMsSinceEpoch = Date.now()
2671
const updatedModules = extractModulesFromTurbopackMessage(msg.data)
2772
for (const module of updatedModules) {
2873
this.#updatedModules.add(module)
2974
}
3075
}
3176

32-
onBuilt(): Built {
77+
onBuilt(): Built | null {
78+
// check that we got *any* `TurbopackMessageAction`, even if
79+
// `updatedModules` is empty (not everything gets recorded there).
80+
const hasUpdates = this.#lastUpdateMsSinceEpoch != null
81+
if (!hasUpdates && this.#deferredReportHmrStartId != null) {
82+
// suppress the update entirely
83+
this.#cancelDeferredReportHmrStart()
84+
return null
85+
}
86+
87+
this.#runDeferredReportHmrStart()
88+
89+
// Turbopack has a debounce which causes every BUILT message to appear
90+
// 30ms late. We don't want to include this latency in our reporting, so
91+
// prefer to use the last TURBOPACK_MESSAGE time.
92+
const endMsSinceEpoch = this.#lastUpdateMsSinceEpoch ?? Date.now()
93+
const latencyMs = endMsSinceEpoch - this.#startMsSinceEpoch!
94+
console.log(`[Fast Refresh] done in ${latencyMs}ms`)
95+
3396
const result = {
97+
hasUpdates,
3498
updatedModules: this.#updatedModules,
3599
startMsSinceEpoch: this.#startMsSinceEpoch!,
36-
// Turbopack has a debounce which causes every BUILT message to appear
37-
// 30ms late. We don't want to include this latency in our reporting, so
38-
// prefer to use the last TURBOPACK_MESSAGE time.
39100
endMsSinceEpoch: this.#lastUpdateMsSinceEpoch ?? Date.now(),
40101
}
41102
this.#updatedModules = new Set()
42103
return result
43104
}
44105
}
45106

46-
export function extractModulesFromTurbopackMessage(
107+
function extractModulesFromTurbopackMessage(
47108
data: TurbopackUpdate | TurbopackUpdate[]
48109
): Set<string> {
49110
const updatedModules: Set<string> = new Set()

0 commit comments

Comments
 (0)