Skip to content

Commit 1c3cc3e

Browse files
committed
fix: handle prefetch correctly
1 parent 13d3c73 commit 1c3cc3e

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

packages/runtime/src/templates/getHandler.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ const { URLSearchParams, URL } = require('url')
1717

1818
const { Bridge } = require('@vercel/node-bridge/bridge')
1919

20-
const { augmentFsModule, getMaxAge, getMultiValueHeaders, getNextServer } = require('./handlerUtils')
20+
const {
21+
augmentFsModule,
22+
getMaxAge,
23+
getMultiValueHeaders,
24+
getPrefetchResponse,
25+
getNextServer,
26+
} = require('./handlerUtils')
2127
/* eslint-enable @typescript-eslint/no-var-requires */
2228

2329
type Mutable<T> = {
@@ -90,6 +96,10 @@ const makeHandler = (conf: NextConfig, app, pageRoot, staticManifest: Array<[str
9096

9197
return async function handler(event: HandlerEvent, context: HandlerContext) {
9298
let requestMode = mode
99+
const prefetchResponse = getPrefetchResponse(event, mode)
100+
if (prefetchResponse) {
101+
return prefetchResponse
102+
}
93103
// Ensure that paths are encoded - but don't double-encode them
94104
event.path = new URL(event.rawUrl).pathname
95105
// Next expects to be able to parse the query from the URL
@@ -164,7 +174,7 @@ export const getHandler = ({ isODB = false, publishDir = '../../../.next', appDi
164174
const { promises } = require("fs");
165175
// We copy the file here rather than requiring from the node module
166176
const { Bridge } = require("./bridge");
167-
const { augmentFsModule, getMaxAge, getMultiValueHeaders, getNextServer } = require('./handlerUtils')
177+
const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, getNextServer } = require('./handlerUtils')
168178
169179
${isODB ? `const { builder } = require("@netlify/functions")` : ''}
170180
const { config } = require("${publishDir}/required-server-files.json")

packages/runtime/src/templates/handlerUtils.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from 'path'
44
import { pipeline } from 'stream'
55
import { promisify } from 'util'
66

7+
import { HandlerEvent, HandlerResponse } from '@netlify/functions'
78
import { http, https } from 'follow-redirects'
89
import type NextNodeServer from 'next/dist/server/next-server'
910

@@ -105,8 +106,8 @@ export const augmentFsModule = ({
105106
const statsOrig = promises.stat
106107
// ...then money-patch it to see if it's requesting a CDN file
107108
promises.readFile = (async (file, options) => {
108-
// In production use the public URL (e.g. https://example.com). Otherwise use the deploy URL, e.g. https://deploy-preview-123--example.netlify.app
109-
const baseUrl = process.env.CONTEXT === 'production' ? process.env.URL : process.env.DEPLOY_PRIME_URL
109+
// In production or dev use the public URL (e.g. https://example.com). Otherwise use the deploy URL, e.g. https://deploy-preview-123--example.netlify.app
110+
const baseUrl = ['production', 'dev'].includes(process.env.CONTEXT) ? process.env.URL : process.env.DEPLOY_PRIME_URL
110111

111112
// We only care about page files
112113
if (file.startsWith(pageRoot)) {
@@ -188,3 +189,19 @@ export const getNextServer = (): NextServerType => {
188189
}
189190
return NextServer
190191
}
192+
/**
193+
* Prefetch requests are used to check for middleware redirects, and shouldn't trigger SSR.
194+
*/
195+
export const getPrefetchResponse = (event: HandlerEvent, mode: string): HandlerResponse | false => {
196+
if (event.headers['x-middleware-prefetch'] && mode === 'ssr') {
197+
return {
198+
statusCode: 200,
199+
body: '{}',
200+
headers: {
201+
'Content-Type': 'application/json',
202+
'x-middleware-skip': '1',
203+
},
204+
}
205+
}
206+
return false
207+
}

0 commit comments

Comments
 (0)