Skip to content

Commit

Permalink
Update to leverage AsyncLocalStorage for app static handling (#40727)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ijjk committed Sep 21, 2022
1 parent 4719517 commit bbeaf08
Show file tree
Hide file tree
Showing 4 changed files with 702 additions and 649 deletions.
5 changes: 0 additions & 5 deletions packages/next/client/components/hooks-server-context.ts
Expand Up @@ -33,7 +33,6 @@ export const CONTEXT_NAMES = {
HeadersContext: 'HeadersContext',
PreviewDataContext: 'PreviewDataContext',
CookiesContext: 'CookiesContext',
StaticGenerationContext: 'StaticGenerationContext',
FetchRevalidateContext: 'FetchRevalidateContext',
} as const

Expand All @@ -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 }
)
32 changes: 24 additions & 8 deletions packages/next/client/components/hooks-server.ts
@@ -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)
}
}
Expand Down
6 changes: 5 additions & 1 deletion packages/next/export/worker.ts
Expand Up @@ -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')
Expand Down Expand Up @@ -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
}
}
Expand Down

0 comments on commit bbeaf08

Please sign in to comment.