Skip to content

Commit a7f2879

Browse files
ztannerunstubbable
andauthored
Backport v14: Retry manifest file loading only in dev mode (#73900) (#74282)
Backports: - #73900 Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
1 parent 2655f6e commit a7f2879

File tree

5 files changed

+39
-7
lines changed

5 files changed

+39
-7
lines changed

packages/next/src/build/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,7 @@ export async function isPageStatic({
15691569
distDir,
15701570
page: originalAppPath || page,
15711571
isAppPath: pageType === 'app',
1572+
isDev: false,
15721573
})
15731574
}
15741575
const Comp = componentsResult.Component as NextComponentType | undefined
@@ -1802,6 +1803,7 @@ export async function hasCustomGetInitialProps({
18021803
distDir,
18031804
page: page,
18041805
isAppPath: false,
1806+
isDev: false,
18051807
})
18061808
let mod = components.ComponentMod
18071809

@@ -1828,6 +1830,7 @@ export async function getDefinedNamedExports({
18281830
distDir,
18291831
page: page,
18301832
isAppPath: false,
1833+
isDev: false,
18311834
})
18321835

18331836
return Object.keys(components.ComponentMod).filter((key) => {

packages/next/src/export/worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ async function exportPageImpl(
257257
distDir,
258258
page,
259259
isAppPath: isAppDir,
260+
isDev: false,
260261
})
261262

262263
const renderOpts: WorkerRenderOpts = {

packages/next/src/server/dev/static-paths-worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export async function loadStaticPaths({
7171
// In `pages/`, the page is the same as the pathname.
7272
page: page || pathname,
7373
isAppPath,
74+
isDev: true,
7475
})
7576

7677
if (!components.getStaticPaths && !isAppPath) {

packages/next/src/server/load-components.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,13 @@ export async function evalManifestWithRetries<T extends object>(
110110

111111
async function loadClientReferenceManifest(
112112
manifestPath: string,
113-
entryName: string
113+
entryName: string,
114+
attempts?: number
114115
) {
115116
try {
116117
const context = await evalManifestWithRetries<{
117118
__RSC_MANIFEST: { [key: string]: ClientReferenceManifest }
118-
}>(manifestPath)
119+
}>(manifestPath, attempts)
119120
return context.__RSC_MANIFEST[entryName]
120121
} catch (err) {
121122
return undefined
@@ -126,10 +127,12 @@ async function loadComponentsImpl<N = any>({
126127
distDir,
127128
page,
128129
isAppPath,
130+
isDev,
129131
}: {
130132
distDir: string
131133
page: string
132134
isAppPath: boolean
135+
isDev: boolean
133136
}): Promise<LoadComponentsReturnType<N>> {
134137
let DocumentMod = {}
135138
let AppMod = {}
@@ -144,16 +147,26 @@ async function loadComponentsImpl<N = any>({
144147
const hasClientManifest =
145148
isAppPath && (page.endsWith('/page') || page === UNDERSCORE_NOT_FOUND_ROUTE)
146149

150+
// In dev mode we retry loading a manifest file to handle a race condition
151+
// that can occur while app and pages are compiling at the same time, and the
152+
// build-manifest is still being written to disk while an app path is
153+
// attempting to load.
154+
const manifestLoadAttempts = isDev ? 3 : 1
155+
147156
// Load the manifest files first
148157
const [
149158
buildManifest,
150159
reactLoadableManifest,
151160
clientReferenceManifest,
152161
serverActionsManifest,
153162
] = await Promise.all([
154-
loadManifestWithRetries<BuildManifest>(join(distDir, BUILD_MANIFEST)),
163+
loadManifestWithRetries<BuildManifest>(
164+
join(distDir, BUILD_MANIFEST),
165+
manifestLoadAttempts
166+
),
155167
loadManifestWithRetries<ReactLoadableManifest>(
156-
join(distDir, REACT_LOADABLE_MANIFEST)
168+
join(distDir, REACT_LOADABLE_MANIFEST),
169+
manifestLoadAttempts
157170
),
158171
hasClientManifest
159172
? loadClientReferenceManifest(
@@ -163,12 +176,14 @@ async function loadComponentsImpl<N = any>({
163176
'app',
164177
page.replace(/%5F/g, '_') + '_' + CLIENT_REFERENCE_MANIFEST + '.js'
165178
),
166-
page.replace(/%5F/g, '_')
179+
page.replace(/%5F/g, '_'),
180+
manifestLoadAttempts
167181
)
168182
: undefined,
169183
isAppPath
170184
? loadManifestWithRetries<ActionManifest>(
171-
join(distDir, 'server', SERVER_REFERENCE_MANIFEST + '.json')
185+
join(distDir, 'server', SERVER_REFERENCE_MANIFEST + '.json'),
186+
manifestLoadAttempts
172187
).catch(() => null)
173188
: null,
174189
])

packages/next/src/server/next-server.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,14 @@ export default class NextNodeServer extends BaseServer {
179179
req: IncomingMessage,
180180
res: ServerResponse
181181
) => void
182+
private isDev: boolean
182183

183184
constructor(options: Options) {
184185
// Initialize super class
185186
super(options)
186187

188+
this.isDev = options.dev ?? false
189+
187190
/**
188191
* This sets environment variable to be used at the time of SSR by head.tsx.
189192
* Using this from process.env allows targeting SSR by calling
@@ -220,11 +223,13 @@ export default class NextNodeServer extends BaseServer {
220223
distDir: this.distDir,
221224
page: '/_document',
222225
isAppPath: false,
226+
isDev: this.isDev,
223227
}).catch(() => {})
224228
loadComponents({
225229
distDir: this.distDir,
226230
page: '/_app',
227231
isAppPath: false,
232+
isDev: this.isDev,
228233
}).catch(() => {})
229234
}
230235

@@ -281,11 +286,17 @@ export default class NextNodeServer extends BaseServer {
281286
distDir: this.distDir,
282287
page,
283288
isAppPath: false,
289+
isDev: this.isDev,
284290
}).catch(() => {})
285291
}
286292

287293
for (const page of Object.keys(appPathsManifest || {})) {
288-
await loadComponents({ distDir: this.distDir, page, isAppPath: true })
294+
await loadComponents({
295+
distDir: this.distDir,
296+
page,
297+
isAppPath: true,
298+
isDev: this.isDev,
299+
})
289300
.then(async ({ ComponentMod }) => {
290301
const webpackRequire = ComponentMod.__next_app__.require
291302
if (webpackRequire?.m) {
@@ -758,6 +769,7 @@ export default class NextNodeServer extends BaseServer {
758769
distDir: this.distDir,
759770
page: pagePath,
760771
isAppPath,
772+
isDev: this.isDev,
761773
})
762774

763775
if (

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy