Skip to content

Commit

Permalink
perf: improve retrieving versionInfo on Turbo HMR (#67309)
Browse files Browse the repository at this point in the history
Identified the bottleneck of Turbopack HMR, one of the reason is that we
run `execSync` to get user's package manager and fetch their registry to
get the latest & canary version of Next.js.
This process was located at the initial of HMR, which could have been
delayed to the initial of the error handling.

- Remove getting user's package manager and just fetch from NPM
regardless the user uses Yarn.
- Used an async IIFE to await the promise of `getVerionInfo` value
inside the synchronous `ws.handleUpgrade`.

> Benchmarked with console inside try-finally

| Version                              | Ready |
|-------------------------------------|---------|
| Canary | 1185ms |
| Delta | 896ms |
| Delta Webpack vs Canary Webpack | -24.39% |

| Version                              | Ready |
|-------------------------------------|---------|
| Canary | 1002ms |
| Delta (Turbopack) | 509ms |
| Delta Turbopack vs Canary Turbopack | -49.20% |

---------

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
Co-authored-by: Tobias Koppers <tobias.koppers@googlemail.com>
  • Loading branch information
3 people committed Jul 9, 2024
1 parent 7f401a8 commit b77f77e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
23 changes: 13 additions & 10 deletions packages/next/src/server/dev/hot-reloader-turbopack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
} from '../lib/render-server'
import { denormalizePagePath } from '../../shared/lib/page-path/denormalize-page-path'
import { trace } from '../../trace'
import type { VersionInfo } from './parse-version-info'
import {
AssetMapper,
type ChangeSubscriptions,
Expand Down Expand Up @@ -494,7 +493,7 @@ export async function createHotReloaderTurbopack(
)
)
const overlayMiddleware = getOverlayMiddleware(project)
const versionInfo: VersionInfo = await getVersionInfo(
const versionInfoPromise = getVersionInfo(
isTestMode || opts.telemetry.isEnabled
)

Expand Down Expand Up @@ -656,15 +655,19 @@ export async function createHotReloaderTurbopack(
}
}

const sync: SyncAction = {
action: HMR_ACTIONS_SENT_TO_BROWSER.SYNC,
errors,
warnings: [],
hash: '',
versionInfo,
}
;(async function () {
const versionInfo = await versionInfoPromise

const sync: SyncAction = {
action: HMR_ACTIONS_SENT_TO_BROWSER.SYNC,
errors,
warnings: [],
hash: '',
versionInfo,
}

sendToClient(client, sync)
sendToClient(client, sync)
})()
})
},

Expand Down
13 changes: 9 additions & 4 deletions packages/next/src/server/dev/hot-reloader-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import { getProperError } from '../../lib/is-error'
import ws from 'next/dist/compiled/ws'
import { existsSync, promises as fs } from 'fs'
import type { UnwrapPromise } from '../../lib/coalesced-function'
import { getRegistry } from '../../lib/helpers/get-registry'
import { parseVersionInfo } from './parse-version-info'
import type { VersionInfo } from './parse-version-info'
import { isAPIRoute } from '../../lib/is-api-route'
Expand Down Expand Up @@ -210,10 +209,16 @@ export async function getVersionInfo(enabled: boolean): Promise<VersionInfo> {
try {
installed = require('next/package.json').version

const registry = getRegistry()
const res = await fetch(`${registry}-/package/next/dist-tags`)
let res

if (!res.ok) return { installed, staleness: 'unknown' }
try {
// use NPM registry regardless user using Yarn
res = await fetch('https://registry.npmjs.org/-/package/next/dist-tags')
} catch {
// ignore fetch errors
}

if (!res || !res.ok) return { installed, staleness: 'unknown' }

const { latest, canary } = await res.json()

Expand Down

0 comments on commit b77f77e

Please sign in to comment.