next
Version:
The React Framework
57 lines (56 loc) • 3.17 kB
JavaScript
import { normalizePagePath } from '../../shared/lib/page-path/normalize-page-path';
import { normalizeLocalePath } from '../../shared/lib/i18n/normalize-locale-path';
import { InvariantError } from '../../shared/lib/invariant-error';
import { AppPathnameNormalizer } from '../normalizers/built/app/app-pathname-normalizer';
import { RouteKind } from '../route-kind';
export const ROUTE_CACHE_DIRECTORY = 'route-cache';
const appPathnameNormalizer = new AppPathnameNormalizer();
/** Convert a runtime route definition to the identity used by response caches. */ export function getResponseCacheOwner(definition) {
return {
kind: definition.kind,
// Pages module names can include a trailing /index in Turbopack. Their
// pathname matches the manifest's source in both bundlers. App modules
// retain groups and parallel slots in their cache identity.
sourceRoute: definition.kind === RouteKind.PAGES ? definition.pathname : definition.page
};
}
/**
* Prerender metadata already identifies its source route. Compare that source
* with the selected module before using its metadata, including negative
* entries and partially specialized fallback shells. Cache storage continues
* to use the full module identity, including groups and parallel slots.
*/ export function isRouteCacheOwner(pathname, owner, prerender, locales) {
if (!prerender) {
return false;
}
// Pages have JSON data routes, App Pages have RSC data routes, and App
// Route Handlers have no separate data route.
const kind = prerender.dataRoute === null ? RouteKind.APP_ROUTE : prerender.dataRoute.endsWith('.json') ? RouteKind.PAGES : prerender.dataRoute.endsWith('.rsc') ? RouteKind.APP_PAGE : undefined;
if (kind !== owner.kind) {
return false;
}
const source = 'srcRoute' in prerender ? prerender.srcRoute : prerender.fallbackSourceRoute;
const prerenderOwner = source ?? (kind === RouteKind.PAGES ? normalizeLocalePath(pathname, locales).pathname : pathname);
return prerenderOwner === (kind === RouteKind.PAGES ? owner.sourceRoute : appPathnameNormalizer.normalize(owner.sourceRoute));
}
/**
* Response keys are opaque to cache handlers. Hash the source route into one
* fixed-length directory, preserving App groups and slots without expanding
* Unicode names or repeating the source directory hierarchy on disk. The
* pathname stays readable and is normalized exactly once before namespacing.
*/ export function getRouteCacheKey(pathname, owner) {
if (!owner) {
throw new InvariantError('Response cache requires a source route');
}
const { sourceRoute } = owner;
let source;
if (process.env.NEXT_RUNTIME === 'edge') {
const sha256 = require('next/dist/compiled/hash.js/sha256');
source = sha256().update(new TextEncoder().encode(sourceRoute)).digest('hex');
} else {
const { createHash } = require('crypto');
source = createHash('sha256').update(sourceRoute).digest('hex');
}
return `/${ROUTE_CACHE_DIRECTORY}/${owner.kind}/${source}/$${normalizePagePath(pathname)}`;
}
//# sourceMappingURL=route-cache-key.js.map