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 <[email protected]>
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)