-
Notifications
You must be signed in to change notification settings - Fork 27.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support dynamicIO in middlware routes and generateStaticParams
route.ts files (and other routes like metadata routes) still need dynamicIO semantics when runnign in edge runtime. This change adds support for configuring dynamicIO for edge routes. It is hard to test properly because edge routes never statically generate and at the moment there are no other observable semantics. If we introduce new semantics that are distinct for dynamicIO that affect dynamic rendering we should update these tests to assert them. Similarly generateStaticParams also needs dynamicIO semantics when configured. Right now it's not quite possible to assert this because there are no observable semantics. We should have one which is that fetchCache is not configurable with dynamicIO on however that isn't implemented yet. This change adds tests but they will need to be updated once we update the fetchCache behavior
- Loading branch information
Showing
23 changed files
with
629 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
test/e2e/app-dir/dynamic-io/app/params/generate-static-params/[slug]/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// TODO once we make fetchCache inert with dynamicIO this test is expected | ||
// to start failing. Right now the force cache causes the fetches to be identical | ||
// and we get only one prebuilt route. once we remove the caching behavior of fetchCache | ||
// when dynamicIO is on we will get more than one route. | ||
// The ideal test wouldn't even use fetchCache but at the moment the default caching for fetch | ||
// is to not cache and so we can't rely on the default to produce a differentiating result. | ||
export const fetchCache = 'default-cache' | ||
|
||
export async function generateStaticParams() { | ||
const set = new Set() | ||
set.add(await fetchRandom('a')) | ||
set.add(await fetchRandom('a')) | ||
|
||
return Array.from(set).map((value) => { | ||
return { | ||
slug: ('' + value).slice(2), | ||
} | ||
}) | ||
} | ||
|
||
export default async function Layout({ children, params }) { | ||
return ( | ||
<> | ||
<h1>{await params.slug}</h1> | ||
<section>{children}</section> | ||
</> | ||
) | ||
} | ||
|
||
const fetchRandom = async (entropy: string) => { | ||
const response = await fetch( | ||
'https://next-data-api-endpoint.vercel.app/api/random?b=' + entropy | ||
) | ||
return response.text() | ||
} |
27 changes: 27 additions & 0 deletions
27
test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/async/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function generateStaticParams() { | ||
return [ | ||
{ | ||
dyn: '1', | ||
}, | ||
] | ||
} | ||
|
||
export async function GET( | ||
request: NextRequest, | ||
props: { params: Promise<{ dyn: string }> } | ||
) { | ||
const { dyn } = await props.params | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
type: 'dynamic params', | ||
param: dyn, | ||
}) | ||
) | ||
} |
29 changes: 29 additions & 0 deletions
29
test/e2e/app-dir/dynamic-io/app/routes/-edge/[dyn]/sync/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { NextRequest, UnsafeUnwrappedParams } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function generateStaticParams() { | ||
return [ | ||
{ | ||
dyn: '1', | ||
}, | ||
] | ||
} | ||
|
||
export async function GET( | ||
request: NextRequest, | ||
props: { params: Promise<{ dyn: string }> } | ||
) { | ||
const dyn = ( | ||
props.params as unknown as UnsafeUnwrappedParams<typeof props.params> | ||
).dyn | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
type: 'dynamic params', | ||
param: dyn, | ||
}) | ||
) | ||
} |
18 changes: 18 additions & 0 deletions
18
test/e2e/app-dir/dynamic-io/app/routes/-edge/dynamic-cookies/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { cookies } from 'next/headers' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const sentinel = (await cookies()).get('x-sentinel') | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
type: 'cookies', | ||
'x-sentinel': sentinel, | ||
}) | ||
) | ||
} |
18 changes: 18 additions & 0 deletions
18
test/e2e/app-dir/dynamic-io/app/routes/-edge/dynamic-headers/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { headers } from 'next/headers' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const sentinel = (await headers()).get('x-sentinel') | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
type: 'headers', | ||
'x-sentinel': sentinel, | ||
}) | ||
) | ||
} |
29 changes: 29 additions & 0 deletions
29
test/e2e/app-dir/dynamic-io/app/routes/-edge/dynamic-stream/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const result = JSON.stringify({ | ||
value: getSentinelValue(), | ||
message: 'dynamic stream', | ||
}) | ||
const part1 = result.slice(0, result.length / 2) | ||
const part2 = result.slice(result.length / 2) | ||
|
||
const encoder = new TextEncoder() | ||
const chunks = [encoder.encode(part1), encoder.encode(part2)] | ||
|
||
let sent = 0 | ||
const stream = new ReadableStream({ | ||
async pull(controller) { | ||
controller.enqueue(chunks[sent++]) | ||
await new Promise((r) => setTimeout(r, 1)) | ||
if (sent === chunks.length) { | ||
controller.close() | ||
} | ||
}, | ||
}) | ||
return new Response(stream) | ||
} |
15 changes: 15 additions & 0 deletions
15
test/e2e/app-dir/dynamic-io/app/routes/-edge/dynamic-url/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const search = request.nextUrl.search | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
search, | ||
}) | ||
) | ||
} |
25 changes: 25 additions & 0 deletions
25
test/e2e/app-dir/dynamic-io/app/routes/-edge/fetch-cached/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const fetcheda = await fetchRandomCached('a') | ||
const fetchedb = await fetchRandomCached('b') | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
random1: fetcheda, | ||
random2: fetchedb, | ||
}) | ||
) | ||
} | ||
|
||
const fetchRandomCached = async (entropy: string) => { | ||
const response = await fetch( | ||
'https://next-data-api-endpoint.vercel.app/api/random?b=' + entropy, | ||
{ cache: 'force-cache' } | ||
) | ||
return response.text() | ||
} |
32 changes: 32 additions & 0 deletions
32
test/e2e/app-dir/dynamic-io/app/routes/-edge/fetch-mixed/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const fetcheda = await fetchRandomCached('a') | ||
const fetchedb = await fetchRandomUncached('b') | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
random1: fetcheda, | ||
random2: fetchedb, | ||
}) | ||
) | ||
} | ||
|
||
const fetchRandomCached = async (entropy: string) => { | ||
const response = await fetch( | ||
'https://next-data-api-endpoint.vercel.app/api/random?b=' + entropy, | ||
{ cache: 'force-cache' } | ||
) | ||
return response.text() | ||
} | ||
|
||
const fetchRandomUncached = async (entropy: string) => { | ||
const response = await fetch( | ||
'https://next-data-api-endpoint.vercel.app/api/random?b=' + entropy | ||
) | ||
return response.text() | ||
} |
27 changes: 27 additions & 0 deletions
27
test/e2e/app-dir/dynamic-io/app/routes/-edge/io-cached/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { unstable_cache as cache } from 'next/cache' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const messagea = await getCachedMessage('hello cached fast', 0) | ||
const messageb = await getCachedMessage('hello cached slow', 20) | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
message1: messagea, | ||
message2: messageb, | ||
}) | ||
) | ||
} | ||
|
||
async function getMessage(echo, delay) { | ||
const tag = ((Math.random() * 10000) | 0).toString(16) | ||
await new Promise((r) => setTimeout(r, delay)) | ||
return `${tag}:${echo}` | ||
} | ||
|
||
const getCachedMessage = cache(getMessage) |
27 changes: 27 additions & 0 deletions
27
test/e2e/app-dir/dynamic-io/app/routes/-edge/io-mixed/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { unstable_cache as cache } from 'next/cache' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const messagea = await getCachedMessage('hello cached fast', 0) | ||
const messageb = await getMessage('hello uncached slow', 20) | ||
return new Response( | ||
JSON.stringify({ | ||
value: getSentinelValue(), | ||
message1: messagea, | ||
message2: messageb, | ||
}) | ||
) | ||
} | ||
|
||
async function getMessage(echo, delay) { | ||
const tag = ((Math.random() * 10000) | 0).toString(16) | ||
await new Promise((r) => setTimeout(r, delay)) | ||
return `${tag}:${echo}` | ||
} | ||
|
||
const getCachedMessage = cache(getMessage) |
14 changes: 14 additions & 0 deletions
14
test/e2e/app-dir/dynamic-io/app/routes/-edge/microtask/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
await Promise.resolve() | ||
const response = JSON.stringify({ | ||
value: getSentinelValue(), | ||
message: 'microtask', | ||
}) | ||
return new Response(response) | ||
} |
28 changes: 28 additions & 0 deletions
28
test/e2e/app-dir/dynamic-io/app/routes/-edge/static-stream-async/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export async function GET(request: NextRequest) { | ||
const response = JSON.stringify({ | ||
value: getSentinelValue(), | ||
message: 'stream response', | ||
}) | ||
const part1 = response.slice(0, Math.floor(response.length / 2)) | ||
const part2 = response.slice(Math.floor(response.length / 2)) | ||
|
||
const encoder = new TextEncoder() | ||
const chunks = [encoder.encode(part1), encoder.encode(part2)] | ||
|
||
let sent = 0 | ||
const stream = new ReadableStream({ | ||
pull(controller) { | ||
controller.enqueue(chunks[sent++]) | ||
if (sent === chunks.length) { | ||
controller.close() | ||
} | ||
}, | ||
}) | ||
return new Response(stream) | ||
} |
28 changes: 28 additions & 0 deletions
28
test/e2e/app-dir/dynamic-io/app/routes/-edge/static-stream-sync/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import type { NextRequest } from 'next/server' | ||
|
||
import { getSentinelValue } from '../../../getSentinelValue' | ||
|
||
export const runtime = 'edge' | ||
|
||
export function GET(request: NextRequest) { | ||
const response = JSON.stringify({ | ||
value: getSentinelValue(), | ||
message: 'stream response', | ||
}) | ||
const part1 = response.slice(0, Math.floor(response.length / 2)) | ||
const part2 = response.slice(Math.floor(response.length / 2)) | ||
|
||
const encoder = new TextEncoder() | ||
const chunks = [encoder.encode(part1), encoder.encode(part2)] | ||
|
||
let sent = 0 | ||
const stream = new ReadableStream({ | ||
pull(controller) { | ||
controller.enqueue(chunks[sent++]) | ||
if (sent === chunks.length) { | ||
controller.close() | ||
} | ||
}, | ||
}) | ||
return new Response(stream) | ||
} |
Oops, something went wrong.