@@ -7,10 +7,6 @@ import contextualize from '@/frame/middleware/context/context'
77import features from '@/versions/middleware/features'
88import breadcrumbs from '@/frame/middleware/context/breadcrumbs'
99import currentProductTree from '@/frame/middleware/context/current-product-tree'
10- import { readCompressedJsonFile } from '@/frame/lib/read-json-file'
11-
12- // scripts/precompute-pageinfo.ts imports this path; missing files fall back to live computation.
13- export const CACHE_FILE_PATH = '.pageinfo-cache.json.br'
1410
1511// Metadata rendering and breadcrumbs need this minimal middleware chain.
1612async function makeRenderingReq ( page : Page , pathname : string ) {
@@ -33,7 +29,7 @@ async function makeRenderingReq(page: Page, pathname: string) {
3329
3430type RenderingReq = Awaited < ReturnType < typeof makeRenderingReq > >
3531
36- async function computeCacheableFromReq ( renderingReq : RenderingReq , page : Page ) {
32+ async function computePageInfoFromReq ( renderingReq : RenderingReq , page : Page ) : Promise < PageInfo > {
3733 const context = renderingReq . context
3834
3935 const title = await page . renderProp ( 'title' , context , { textOnly : true } )
@@ -67,24 +63,11 @@ async function computeBreadcrumbsFromReq(renderingReq: RenderingReq) {
6763 return renderingReq . context . breadcrumbs as Breadcrumb [ ] | undefined
6864}
6965
70- // Cache only title, intro, and product.
71- // Breadcrumbs compute cheaply on cache hits and would bloat the cache file and dictionary.
72- export async function getCacheablePageInfo ( page : Page , pathname : string ) {
73- const renderingReq = await makeRenderingReq ( page , pathname )
74- return computeCacheableFromReq ( renderingReq , page )
75- }
76-
77- // Breadcrumbs cost less than title and intro rendering, so cache hits compute them.
78- export async function getBreadcrumbsForPage ( page : Page , pathname : string ) {
79- const renderingReq = await makeRenderingReq ( page , pathname )
80- return computeBreadcrumbsFromReq ( renderingReq )
81- }
82-
83- // getPageInfo reuses one rendering request on cache misses.
66+ // getPageInfo reuses one rendering request.
8467// contextualize, shortVersions, and features run once for metadata and breadcrumbs.
85- export async function getPageInfo ( page : Page , pathname : string ) {
68+ export async function getPageInfo ( page : Page , pathname : string ) : Promise < PageInfoWithBreadcrumbs > {
8669 const renderingReq = await makeRenderingReq ( page , pathname )
87- const base = await computeCacheableFromReq ( renderingReq , page )
70+ const base = await computePageInfoFromReq ( renderingReq , page )
8871 const pageBreadcrumbs = await computeBreadcrumbsFromReq ( renderingReq )
8972 return { ...base , breadcrumbs : pageBreadcrumbs }
9073}
@@ -108,61 +91,16 @@ async function getProductPageInfo(page: Page, context: Context) {
10891 return _productPageCache [ cacheKey ]
10992}
11093
111- type CachedPageInfoEntry = {
94+ type PageInfo = {
11295 title : string
11396 intro : string
11497 product : string
11598}
11699
117- type CachedPageInfo = {
118- [ url : string ] : CachedPageInfoEntry
119- }
120-
121100type Breadcrumb = { href : string ; title : string }
122101
123- type PageInfoWithBreadcrumbs = CachedPageInfoEntry & {
102+ type PageInfoWithBreadcrumbs = PageInfo & {
124103 breadcrumbs ?: Breadcrumb [ ]
125- cacheInfo ?: string
126- }
127-
128- // getPageInfoFromCache does not fill the in-memory cache on misses.
129- // Production sees each HTTP GET once per deploy because the CDN caches it until purge.
130- // Local review does not need this cache path for performance.
131- // CI warms the precomputed cache with npm run precompute-pageinfo before vitest.
132- let _cache : CachedPageInfo | null = null
133- export async function getPageInfoFromCache (
134- page : Page ,
135- pathname : string ,
136- ) : Promise < PageInfoWithBreadcrumbs > {
137- let cacheInfo = ''
138- if ( _cache === null ) {
139- try {
140- _cache = readCompressedJsonFile ( CACHE_FILE_PATH ) as CachedPageInfo
141- cacheInfo = 'initial-load'
142- } catch ( error ) {
143- cacheInfo = 'initial-fail'
144- if ( error instanceof Error && ( error as NodeJS . ErrnoException ) . code !== 'ENOENT' ) {
145- throw error
146- }
147- _cache = { }
148- }
149- }
150-
151- const cached = _cache [ pathname ]
152- if ( ! cacheInfo ) {
153- cacheInfo = cached ? 'hit' : 'miss'
154- }
155-
156- let meta : PageInfoWithBreadcrumbs
157- if ( cached ) {
158- // The precomputed cache omits breadcrumbs because cache hits can compute them cheaply.
159- const pageBreadcrumbs = await getBreadcrumbsForPage ( page , pathname )
160- meta = { ...cached , breadcrumbs : pageBreadcrumbs }
161- } else {
162- meta = await getPageInfo ( page , pathname )
163- }
164- meta . cacheInfo = cacheInfo
165- return meta
166104}
167105
168106// pageValidationMiddleware follows redirects before getMetadata.
@@ -189,11 +127,9 @@ export async function getMetadata(req: ExtendedRequestWithPageInfo) {
189127 throw new Error ( `pathname '${ pathname } ' not one of the page's permalinks` )
190128 }
191129
192- const fromCache = await getPageInfoFromCache ( page , pathname )
193- const { cacheInfo, ...meta } = fromCache
130+ const meta = await getPageInfo ( page , pathname )
194131
195132 return {
196133 meta : { ...meta , documentType, ...( redirectedFrom && { redirectedFrom } ) } ,
197- cacheInfo,
198134 }
199135}
0 commit comments