Update to leverage AsyncLocalStorage for app static handling (#40727)

Leverages `AsyncLocalStorage` when available for handling static generation context and falls back to requiring render to be isolated when `AsyncLocalStorage` is not available. 

Note: most changes are spacing so toggling to ignore spacing may make reviewing easier
This commit is contained in:
JJ Kasper 2022-09-20 17:00:19 -07:00 committed by GitHub
parent 4719517381
commit bbeaf081ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 711 additions and 658 deletions

View file

@ -33,7 +33,6 @@ export const CONTEXT_NAMES = {
HeadersContext: 'HeadersContext',
PreviewDataContext: 'PreviewDataContext',
CookiesContext: 'CookiesContext',
StaticGenerationContext: 'StaticGenerationContext',
FetchRevalidateContext: 'FetchRevalidateContext',
} as const
@ -42,7 +41,3 @@ export const PreviewDataContext = createContext(
CONTEXT_NAMES.PreviewDataContext
)
export const CookiesContext = createContext(CONTEXT_NAMES.CookiesContext)
export const StaticGenerationContext = createContext(
CONTEXT_NAMES.StaticGenerationContext,
{ isStaticGeneration: false }
)

View file

@ -1,24 +1,40 @@
import type { AsyncLocalStorage } from 'async_hooks'
import { useContext } from 'react'
import {
HeadersContext,
PreviewDataContext,
CookiesContext,
DynamicServerError,
StaticGenerationContext,
} from './hooks-server-context'
export function useTrackStaticGeneration() {
return useContext<
typeof import('./hooks-server-context').StaticGenerationContext
>(StaticGenerationContext)
export interface StaticGenerationStore {
inUse?: boolean
pathname?: string
revalidate?: number
fetchRevalidate?: number
isStaticGeneration?: boolean
}
export let staticGenerationAsyncStorage:
| AsyncLocalStorage<StaticGenerationStore>
| StaticGenerationStore = {}
if (process.env.NEXT_RUNTIME !== 'edge' && typeof window === 'undefined') {
staticGenerationAsyncStorage =
new (require('async_hooks').AsyncLocalStorage)()
}
function useStaticGenerationBailout(reason: string) {
const staticGenerationContext = useTrackStaticGeneration()
const staticGenerationStore =
staticGenerationAsyncStorage && 'getStore' in staticGenerationAsyncStorage
? staticGenerationAsyncStorage?.getStore()
: staticGenerationAsyncStorage
if (staticGenerationContext.isStaticGeneration) {
if (staticGenerationStore?.isStaticGeneration) {
// TODO: honor the dynamic: 'force-static'
staticGenerationContext.revalidate = 0
if (staticGenerationStore) {
staticGenerationStore.revalidate = 0
}
throw new DynamicServerError(reason)
}
}

View file

@ -28,6 +28,7 @@ import RenderResult from '../server/render-result'
import isError from '../lib/is-error'
import { addRequestMeta } from '../server/request-meta'
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'
import { REDIRECT_ERROR_CODE } from '../client/components/redirect'
loadRequireHook()
const envConfig = require('../shared/lib/runtime-config')
@ -419,7 +420,10 @@ export default async function exportPage({
)
}
} catch (err) {
if (!(err instanceof DynamicServerError)) {
if (
!(err instanceof DynamicServerError) &&
(err as any).code !== REDIRECT_ERROR_CODE
) {
throw err
}
}

File diff suppressed because it is too large Load diff