fix(turbopack): build all parallel routes to make sure HMR works (#67222)
### What? Parallel routes build in a weird and render in a weird way. To render next.js always uses the last parallel route (alphabetically I think) as that's most likely to be the root. Building works in the opposite order, it goes from the first to the last. This is fine for the first render, but after that the renderer will only check if the file for the last parallel route has a bundle on disk and never request it to be updated. 1. match on routes 2. build match 3. check if the last parallel route bundle exists on disk - if it doesn't so go back to step 2 with the next match - the actual match gets thrown away 4. render with the bundle for the last parallel route The condition in step 3 will always be true after an update, because it was built for a previous request To fix this, turbopack will now emit all parallel routes that match a path every time one of them gets requested. Closes PACK-3078 Fixes #65836
This commit is contained in:
parent
d8d8b53cd1
commit
4df48390db
1 changed files with 58 additions and 44 deletions
|
@ -80,6 +80,7 @@ import {
|
|||
} from './turbopack/entry-key'
|
||||
import { FAST_REFRESH_RUNTIME_RELOAD } from './messages'
|
||||
import { generateEncryptionKeyBase64 } from '../app-render/encryption-utils'
|
||||
import { isAppPageRouteDefinition } from '../route-definitions/app-page-route-definition'
|
||||
|
||||
const wsServer = new ws.Server({ noServer: true })
|
||||
const isTestMode = !!(
|
||||
|
@ -762,7 +763,7 @@ export async function createHotReloaderTurbopack(
|
|||
page: inputPage,
|
||||
// Unused parameters
|
||||
// clientOnly,
|
||||
// appPaths,
|
||||
appPaths,
|
||||
definition,
|
||||
isApp,
|
||||
url: requestUrl,
|
||||
|
@ -784,6 +785,14 @@ export async function createHotReloaderTurbopack(
|
|||
const page = routeDef.page
|
||||
const pathname = definition?.pathname ?? inputPage
|
||||
|
||||
let pages = appPaths ?? [page]
|
||||
|
||||
// If the route is actually an app page route, then we should have access
|
||||
// to the app route definition, and therefore, the appPaths from it.
|
||||
if (!appPaths && definition && isAppPageRouteDefinition(definition)) {
|
||||
pages = definition.appPaths
|
||||
}
|
||||
|
||||
if (page === '/_error') {
|
||||
let finishBuilding = startBuilding(pathname, requestUrl, false)
|
||||
try {
|
||||
|
@ -811,11 +820,17 @@ export async function createHotReloaderTurbopack(
|
|||
await currentEntriesHandling
|
||||
|
||||
const isInsideAppDir = routeDef.bundlePath.startsWith('app/')
|
||||
|
||||
const finishBuilding = startBuilding(pathname, requestUrl, false)
|
||||
try {
|
||||
// we need to build all parallel routes, so we loop over them here
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-shadow -- intentionally shadowed*/
|
||||
for (const page of pages) {
|
||||
const normalizedAppPage = normalizedPageToTurbopackStructureRoute(
|
||||
page,
|
||||
extname(routeDef.filename)
|
||||
)
|
||||
|
||||
const route = isInsideAppDir
|
||||
? currentEntrypoints.app.get(normalizedAppPage)
|
||||
: currentEntrypoints.page.get(page)
|
||||
|
@ -837,8 +852,6 @@ export async function createHotReloaderTurbopack(
|
|||
throw new Error(`mis-matched route type: isApp && page for ${page}`)
|
||||
}
|
||||
|
||||
const finishBuilding = startBuilding(pathname, requestUrl, false)
|
||||
try {
|
||||
await handleRouteType({
|
||||
dev: true,
|
||||
page,
|
||||
|
@ -859,6 +872,7 @@ export async function createHotReloaderTurbopack(
|
|||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
finishBuilding()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue