Skip to content

Commit 24873b3

Browse files
committed
fix(turbopack): Suppress logging for short no-op turbopack HMRs
1 parent e03cd6b commit 24873b3

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ function processMessage(
267267
function handleHotUpdate() {
268268
if (process.env.TURBOPACK) {
269269
const hmrUpdate = turbopackHmr!.onBuilt()
270-
if (hmrUpdate != null) {
270+
if (hmrUpdate != null && hmrUpdate.hasUpdates) {
271271
reportHmrLatency(
272272
sendMessage,
273273
[...hmrUpdate.updatedModules],
@@ -306,8 +306,8 @@ function processMessage(
306306
} else {
307307
webpackStartMsSinceEpoch = Date.now()
308308
setPendingHotUpdateWebpack()
309+
console.log('[Fast Refresh] rebuilding')
309310
}
310-
console.log('[Fast Refresh] rebuilding')
311311
break
312312
}
313313
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:
@@ -395,11 +395,11 @@ function processMessage(
395395
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
396396
data: obj.data,
397397
})
398-
dispatcher.onRefresh()
399398
if (RuntimeErrorHandler.hadRuntimeError) {
400399
console.warn(REACT_REFRESH_FULL_RELOAD_FROM_ERROR)
401400
performFullReload(null, sendMessage)
402401
}
402+
dispatcher.onRefresh()
403403
turbopackHmr!.onTurbopackMessage(obj)
404404
break
405405
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ function handleSuccess() {
133133

134134
if (process.env.TURBOPACK) {
135135
const hmrUpdate = turbopackHmr!.onBuilt()
136-
if (hmrUpdate != null) {
136+
if (hmrUpdate != null && hmrUpdate.hasUpdates) {
137137
reportHmrLatency(
138138
sendMessage,
139139
[...hmrUpdate.updatedModules],
@@ -275,8 +275,8 @@ function processMessage(obj: HMR_ACTION_TYPES) {
275275
turbopackHmr!.onBuilding()
276276
} else {
277277
webpackStartMsSinceEpoch = Date.now()
278+
console.log('[Fast Refresh] rebuilding')
278279
}
279-
console.log('[Fast Refresh] rebuilding')
280280
break
281281
}
282282
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:

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

Lines changed: 57 additions & 6 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 HmrUpdate {
15+
hasUpdates: boolean
516
updatedModules: Set<string>
617
startMsSinceEpoch: number
718
endMsSinceEpoch: number
@@ -11,17 +22,51 @@ 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) {
@@ -30,17 +75,23 @@ export class TurbopackHmr {
3075
}
3176

3277
onBuilt(): HmrUpdate | null {
33-
// it's possible for `this.#startMsSinceEpoch` to not be set if this was the initial
34-
// computation, just return null in this case.
35-
if (this.#startMsSinceEpoch == null) {
78+
// Check that we got *any* `TurbopackMessageAction`, even if `updatedModules` is empty (not
79+
// everything gets recorded there).
80+
//
81+
// This also handles for the case where `onBuilt` gets called before `onBuilding`, which can
82+
// happen during initial page load. We should ignore this.
83+
const hasUpdates = this.#lastUpdateMsSinceEpoch != null
84+
if (!hasUpdates && this.#deferredReportHmrStartId != null) {
85+
// suppress the update entirely
86+
this.#cancelDeferredReportHmrStart()
3687
return null
3788
}
89+
this.#runDeferredReportHmrStart()
90+
3891
const result = {
92+
hasUpdates,
3993
updatedModules: this.#updatedModules,
4094
startMsSinceEpoch: this.#startMsSinceEpoch!,
41-
// Turbopack has a debounce which causes every BUILT message to appear
42-
// 30ms late. We don't want to include this latency in our reporting, so
43-
// prefer to use the last TURBOPACK_MESSAGE time.
4495
endMsSinceEpoch: this.#lastUpdateMsSinceEpoch ?? Date.now(),
4596
}
4697
this.#updatedModules = new Set()

0 commit comments

Comments
 (0)