perf: improve retrieving versionInfo on Turbo HMR (#67309)

### Why?

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.

### How?

- 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`.

### Benchmark

> Benchmarked with console inside try-finally

#### Webpack -- no cache

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

#### Turbopack

| 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>
This commit is contained in:
Jiwon Choi 2024-07-02 02:16:22 +09:00 committed by GitHub
parent 0e6e83c33d
commit ef83433c3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 15 additions and 13 deletions

View file

@ -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,
@ -504,7 +503,7 @@ export async function createHotReloaderTurbopack(
)
)
const overlayMiddleware = getOverlayMiddleware(project)
const versionInfo: VersionInfo = await getVersionInfo(
const versionInfoPromise = getVersionInfo(
isTestMode || opts.telemetry.isEnabled
)
@ -666,6 +665,9 @@ export async function createHotReloaderTurbopack(
}
}
;(async function () {
const versionInfo = await versionInfoPromise
const sync: SyncAction = {
action: HMR_ACTIONS_SENT_TO_BROWSER.SYNC,
errors,
@ -675,6 +677,7 @@ export async function createHotReloaderTurbopack(
}
sendToClient(client, sync)
})()
})
},

View file

@ -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'
@ -202,11 +201,11 @@ export async function getVersionInfo(enabled: boolean): Promise<VersionInfo> {
try {
installed = require('next/package.json').version
const registry = getRegistry()
let res
try {
res = await fetch(`${registry}-/package/next/dist-tags`)
// use NPM registry regardless user using Yarn
res = await fetch('https://registry.npmjs.org/-/package/next/dist-tags')
} catch {
// ignore fetch errors
}