Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dbdf03e

Browse files
committed
feat: allow next middleware to use edge cache
1 parent 5d12caf commit dbdf03e

File tree

10 files changed

+147
-1
lines changed

10 files changed

+147
-1
lines changed

‎src/build/functions/edge.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,10 @@ const buildHandlerDefinition = (
172172
const functionName = name.endsWith('middleware')
173173
? 'Next.js Middleware Handler'
174174
: `Next.js Edge Handler: ${page}`
175-
const cache = name.endsWith('middleware') ? undefined : ('manual' as const)
175+
const cache =
176+
!process.env.NEXT_MIDDLEWARE_CACHE && name.endsWith('middleware')
177+
? undefined
178+
: ('manual' as const)
176179
const generator = `${ctx.pluginName}@${ctx.pluginVersion}`
177180

178181
return augmentMatchers(matchers, ctx).map((matcher) => ({
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const metadata = {
2+
title: 'Simple Next App',
3+
description: 'Description for Simple Next App',
4+
}
5+
6+
export default function RootLayout({ children }) {
7+
return (
8+
<html lang="en">
9+
<body>{children}</body>
10+
</html>
11+
)
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Home() {
2+
return (
3+
<main>
4+
<h1>Home</h1>
5+
</main>
6+
)
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function EdgeCached() {
2+
return (
3+
<main>
4+
<h1>If middleware works, we shoudn't get here</h1>
5+
</main>
6+
)
7+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { headers } from 'next/headers'
2+
3+
export default function Page() {
4+
const headersList = headers()
5+
const message = headersList.get('x-hello-from-middleware-req')
6+
7+
return (
8+
<main>
9+
<h1>Message from middleware: {message}</h1>
10+
</main>
11+
)
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function EdgeUncached() {
2+
return (
3+
<main>
4+
<h1>If middleware works, we shoudn't get here</h1>
5+
</main>
6+
)
7+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { NextRequest } from 'next/server'
2+
import { NextResponse } from 'next/server'
3+
4+
export function middleware(request: NextRequest) {
5+
const response = getResponse(request)
6+
7+
response.headers.append('Deno' in globalThis ? 'x-deno' : 'x-node', Date.now().toString())
8+
response.headers.set('x-hello-from-middleware-res', 'hello')
9+
10+
return response
11+
}
12+
13+
const getResponse = (request: NextRequest) => {
14+
const requestHeaders = new Headers(request.headers)
15+
16+
requestHeaders.set('x-hello-from-middleware-req', 'hello')
17+
18+
if (request.nextUrl.pathname === '/test/cached') {
19+
return NextResponse.next({
20+
request: {
21+
headers: new Headers({
22+
...requestHeaders,
23+
'netlify-cdn-cache-control': 's-maxage=31536000, durable',
24+
}),
25+
},
26+
})
27+
}
28+
29+
if (request.nextUrl.pathname === '/test/uncached') {
30+
return NextResponse.next({
31+
request: {
32+
headers: requestHeaders,
33+
},
34+
})
35+
}
36+
37+
return NextResponse.json({ error: 'Error' }, { status: 500 })
38+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/** @type {import('next').NextConfig} */
2+
const nextConfig = {
3+
output: 'standalone',
4+
eslint: {
5+
ignoreDuringBuilds: true,
6+
},
7+
}
8+
9+
module.exports = nextConfig
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "middleware-edge-cache",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"postinstall": "next build",
7+
"dev": "next dev",
8+
"build": "next build"
9+
},
10+
"dependencies": {
11+
"next": "latest",
12+
"react": "18.2.0",
13+
"react-dom": "18.2.0"
14+
}
15+
}

‎tests/integration/edge-handler.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,4 +625,40 @@ describe('page router', () => {
625625
expect(bodyFr.nextUrlPathname).toBe('/json')
626626
expect(bodyFr.nextUrlLocale).toBe('fr')
627627
})
628+
629+
test<FixtureTestContext>('should use edge caching', async (ctx) => {
630+
vi.stubEnv('NEXT_MIDDLEWARE_CACHE', 'true')
631+
632+
await createFixture('middleware-edge-cache', ctx)
633+
await runPlugin(ctx)
634+
const origin = await LocalServer.run(async (req, res) => {
635+
res.write(
636+
JSON.stringify({
637+
url: req.url,
638+
headers: req.headers,
639+
}),
640+
)
641+
res.end()
642+
})
643+
ctx.cleanup?.push(() => origin.stop())
644+
645+
const response = await invokeEdgeFunction(ctx, {
646+
functions: ['___netlify-edge-handler-middleware'],
647+
origin,
648+
url: `/test/cached`,
649+
})
650+
expect(response.status).toBe(200)
651+
652+
expect(response.headers.has('netlify-cdn-cache-control')).toBeTruthy()
653+
expect(response.headers.get('netlify-cdn-cache-control')).toBe('s-maxage=31536000, durable')
654+
655+
const responseUncached = await invokeEdgeFunction(ctx, {
656+
functions: ['___netlify-edge-handler-middleware'],
657+
origin,
658+
url: `/test/uncached`,
659+
})
660+
expect(responseUncached.status).toBe(200)
661+
662+
expect(responseUncached.headers.has('netlify-cdn-cache-control')).toBeFalsy()
663+
})
628664
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /