mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
99 lines
5.0 KiB
JavaScript
99 lines
5.0 KiB
JavaScript
import React from 'react';
|
|
import { DynamicServerError } from '../../client/components/hooks-server-context';
|
|
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout';
|
|
import { getPathname } from '../../lib/url';
|
|
const hasPostpone = typeof React.unstable_postpone === 'function';
|
|
export function createPrerenderState(isDebugSkeleton) {
|
|
return {
|
|
isDebugSkeleton,
|
|
dynamicAccesses: []
|
|
};
|
|
}
|
|
export function markCurrentScopeAsDynamic(store, expression) {
|
|
const pathname = getPathname(store.urlPathname);
|
|
if (store.isUnstableCacheCallback) {
|
|
return;
|
|
} else if (store.dynamicShouldError) {
|
|
throw new StaticGenBailoutError(`Route ${pathname} with \`dynamic = "error"\` couldn't be rendered statically because it used \`${expression}\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`);
|
|
} else if (store.prerenderState) {
|
|
postponeWithTracking(store.prerenderState, expression, pathname);
|
|
} else {
|
|
store.revalidate = 0;
|
|
if (store.isStaticGeneration) {
|
|
const err = new DynamicServerError(`Route ${pathname} couldn't be rendered statically because it used ${expression}. See more info here: https://nextjs.org/docs/messages/dynamic-server-error`);
|
|
store.dynamicUsageDescription = expression;
|
|
store.dynamicUsageStack = err.stack;
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
export function trackDynamicDataAccessed(store, expression) {
|
|
const pathname = getPathname(store.urlPathname);
|
|
if (store.isUnstableCacheCallback) {
|
|
throw new Error(`Route ${pathname} used "${expression}" inside a function cached with "unstable_cache(...)". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use "${expression}" outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`);
|
|
} else if (store.dynamicShouldError) {
|
|
throw new StaticGenBailoutError(`Route ${pathname} with \`dynamic = "error"\` couldn't be rendered statically because it used \`${expression}\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`);
|
|
} else if (store.prerenderState) {
|
|
postponeWithTracking(store.prerenderState, expression, pathname);
|
|
} else {
|
|
store.revalidate = 0;
|
|
if (store.isStaticGeneration) {
|
|
const err = new DynamicServerError(`Route ${pathname} couldn't be rendered statically because it used ${expression}. See more info here: https://nextjs.org/docs/messages/dynamic-server-error`);
|
|
store.dynamicUsageDescription = expression;
|
|
store.dynamicUsageStack = err.stack;
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
export function Postpone({ reason, prerenderState, pathname }) {
|
|
postponeWithTracking(prerenderState, reason, pathname);
|
|
}
|
|
export function trackDynamicFetch(store, expression) {
|
|
if (!store.prerenderState || store.isUnstableCacheCallback) return;
|
|
postponeWithTracking(store.prerenderState, expression, store.urlPathname);
|
|
}
|
|
function postponeWithTracking(prerenderState, expression, pathname) {
|
|
assertPostpone();
|
|
const reason = `Route ${pathname} needs to bail out of prerendering at this point because it used ${expression}. ` + `React throws this special object to indicate where. It should not be caught by ` + `your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`;
|
|
prerenderState.dynamicAccesses.push({
|
|
stack: prerenderState.isDebugSkeleton ? new Error().stack : undefined,
|
|
expression
|
|
});
|
|
React.unstable_postpone(reason);
|
|
}
|
|
export function usedDynamicAPIs(prerenderState) {
|
|
return prerenderState.dynamicAccesses.length > 0;
|
|
}
|
|
export function formatDynamicAPIAccesses(prerenderState) {
|
|
return prerenderState.dynamicAccesses.filter((access)=>typeof access.stack === 'string' && access.stack.length > 0).map(({ expression, stack })=>{
|
|
stack = stack.split('\n').slice(4).filter((line)=>{
|
|
if (line.includes('node_modules/next/')) {
|
|
return false;
|
|
}
|
|
if (line.includes(' (<anonymous>)')) {
|
|
return false;
|
|
}
|
|
if (line.includes(' (node:')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}).join('\n');
|
|
return `Dynamic API Usage Debug - ${expression}:\n${stack}`;
|
|
});
|
|
}
|
|
function assertPostpone() {
|
|
if (!hasPostpone) {
|
|
throw new Error(`Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js`);
|
|
}
|
|
}
|
|
export function createPostponedAbortSignal(reason) {
|
|
assertPostpone();
|
|
const controller = new AbortController();
|
|
try {
|
|
React.unstable_postpone(reason);
|
|
} catch (x) {
|
|
controller.abort(x);
|
|
}
|
|
return controller.signal;
|
|
}
|