@@ -2,10 +2,18 @@ import { toComputeResponse, toReqRes } from '@fastly/http-compute-js'
2
2
import { HeadersSentEvent } from '@fastly/http-compute-js/dist/http-compute-js/http-outgoing.js'
3
3
import type { NextConfigComplete } from 'next/dist/server/config-shared.js'
4
4
import type { WorkerRequestHandler } from 'next/dist/server/lib/types.js'
5
+ import { readFileSync } from 'node:fs'
6
+ import { join } from 'node:path/posix'
7
+ import { CacheEntryValue , PageCacheValue } from '../../build/content/prerendered.js'
5
8
import { RUN_DIR } from '../constants.js'
6
9
import { setCacheControlHeaders , setCacheTagsHeaders , setVaryHeaders } from '../headers.js'
10
+ import { nextResponseProxy } from '../revalidate.js'
7
11
8
- let nextHandler : WorkerRequestHandler , nextConfig : NextConfigComplete
12
+ export type PageCacheEntry = CacheEntryValue & { value : PageCacheValue }
13
+
14
+ let nextHandler : WorkerRequestHandler ,
15
+ nextConfig : NextConfigComplete ,
16
+ cacheEntry : PageCacheEntry | undefined | null
9
17
10
18
export default async ( request : Request ) => {
11
19
if ( ! nextHandler ) {
@@ -14,6 +22,8 @@ export default async (request: Request) => {
14
22
nextConfig = await getRunConfig ( )
15
23
setRunConfig ( nextConfig )
16
24
25
+ cacheEntry = await getCacheEntry ( request )
26
+
17
27
const { getMockedRequestHandlers } = await import ( './next.cjs' )
18
28
19
29
; [ nextHandler ] = await getMockedRequestHandlers ( {
@@ -26,27 +36,54 @@ export default async (request: Request) => {
26
36
27
37
const { req, res } = toReqRes ( request )
28
38
29
- res . prependListener ( '_headersSent' , ( event : HeadersSentEvent ) => {
39
+ const resProxy = nextResponseProxy ( res )
40
+
41
+ resProxy . prependListener ( '_headersSent' , ( event : HeadersSentEvent ) => {
30
42
const headers = new Headers ( event . headers )
31
43
setCacheControlHeaders ( headers )
32
- setCacheTagsHeaders ( headers )
44
+ setCacheTagsHeaders ( request , headers , cacheEntry )
33
45
setVaryHeaders ( headers , request , nextConfig )
34
46
event . headers = Object . fromEntries ( headers . entries ( ) )
35
47
// console.log('Modified response headers:', JSON.stringify(event.headers, null, 2))
36
48
} )
37
49
38
50
try {
39
- console . log ( 'Next server request:' , req . url )
40
- await nextHandler ( req , res )
51
+ // console.log('Next server request:', req.url)
52
+ await nextHandler ( req , resProxy )
41
53
} catch ( error ) {
42
54
console . error ( error )
43
- res . statusCode = 500
44
- res . end ( 'Internal Server Error' )
55
+ resProxy . statusCode = 500
56
+ resProxy . end ( 'Internal Server Error' )
45
57
}
46
58
47
59
// log the response from Next.js
48
- const response = { headers : res . getHeaders ( ) , statusCode : res . statusCode }
60
+ const response = {
61
+ headers : resProxy . getHeaders ( ) ,
62
+ statusCode : resProxy . statusCode ,
63
+ }
49
64
// console.log('Next server response:', JSON.stringify(response, null, 2))
50
65
51
- return toComputeResponse ( res )
66
+ return toComputeResponse ( resProxy )
67
+ }
68
+
69
+ const prerenderManifest = JSON . parse (
70
+ readFileSync ( join ( process . cwd ( ) , '.next/prerender-manifest.json' ) , 'utf-8' ) ,
71
+ )
72
+
73
+ const getCacheEntry = async ( request : Request ) => {
74
+ // dynamically importing to avoid calling NetlifyCacheHandler beforhand
75
+ // @ts -expect-error
76
+ const NetlifyCacheHandler = await import ( '../../../dist/run/handlers/cache.cjs' )
77
+ // Have to assign NetlifyCacheHandler.default to new variable to prevent error: `X is not a constructor`
78
+ const CacheHandler = NetlifyCacheHandler . default
79
+ const cache = new CacheHandler ( {
80
+ _appDir : true ,
81
+ revalidateTags : [ ] ,
82
+ _requestHandler : { } ,
83
+ } )
84
+ const path = new URL ( request . url ) . pathname
85
+ // Checking if route is in prerender manifest before retrieving pageData from Blob
86
+ if ( prerenderManifest . routes [ path ] ) {
87
+ return await cache . get ( path , { type : 'json' } )
88
+ }
52
89
}
0 commit comments