rsnext/packages/next/client/components/hooks-server.ts
JJ Kasper bbeaf081ae
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
2022-09-21 00:00:19 +00:00

55 lines
1.5 KiB
TypeScript

import type { AsyncLocalStorage } from 'async_hooks'
import { useContext } from 'react'
import {
HeadersContext,
PreviewDataContext,
CookiesContext,
DynamicServerError,
} from './hooks-server-context'
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 staticGenerationStore =
staticGenerationAsyncStorage && 'getStore' in staticGenerationAsyncStorage
? staticGenerationAsyncStorage?.getStore()
: staticGenerationAsyncStorage
if (staticGenerationStore?.isStaticGeneration) {
// TODO: honor the dynamic: 'force-static'
if (staticGenerationStore) {
staticGenerationStore.revalidate = 0
}
throw new DynamicServerError(reason)
}
}
export function useHeaders() {
useStaticGenerationBailout('useHeaders')
return useContext(HeadersContext)
}
export function usePreviewData() {
useStaticGenerationBailout('usePreviewData')
return useContext(PreviewDataContext)
}
export function useCookies() {
useStaticGenerationBailout('useCookies')
return useContext(CookiesContext)
}