-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add test setup for edge functions (#84)
* tests: add test setup for edge functions chore: update * chore: update * chore: install deno on CI * chore: install specific deno version to match edge-bundler * chore: update test sharding * chore: update path * chore: update * chore: increase timings * chore: fight flakyness with more hardware * chore: fix sharding * chore: increase timeout
- Loading branch information
1 parent
a31816e
commit 90bb11b
Showing
26 changed files
with
985 additions
and
59 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ dist/ | |
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ | ||
|
||
deno.lock |
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,4 @@ | ||
{ | ||
"deno.enablePaths": ["tools/deno", "edge-runtime"], | ||
"deno.unstable": true | ||
} |
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,7 @@ | ||
{ | ||
"lint": { | ||
"files": { | ||
"include": ["edge-runtime/middleware.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,22 @@ | ||
import type { Config, Context } from '@netlify/edge-functions' | ||
|
||
// import nextConfig from '../edge-shared/nextConfig.json' assert { type: 'json' } | ||
|
||
export async function handleMiddleware(req: Request, context: Context, nextHandler: () => any) { | ||
// Don't run in dev | ||
if (Deno.env.get('NETLIFY_DEV')) { | ||
return | ||
} | ||
|
||
const url = new URL(req.url) | ||
console.log('from handleMiddleware', url) | ||
// const req = new IncomingMessage(internalEvent); | ||
// const res = new ServerlessResponse({ | ||
// method: req.method ?? "GET", | ||
// headers: {}, | ||
// }); | ||
// | ||
// const request = buildNextRequest(req, context, nextConfig) | ||
|
||
return Response.json({ success: true }) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,144 @@ | ||
import { mkdir, rm } from 'node:fs/promises' | ||
import { join } from 'node:path' | ||
import { EDGE_HANDLER_DIR } from '../constants.js' | ||
|
||
/** | ||
* Create a Netlify edge function to run the Next.js server | ||
*/ | ||
export const createEdgeHandler = async () => { | ||
// reset the handler directory | ||
await rm(join(process.cwd(), EDGE_HANDLER_DIR), { recursive: true, force: true }) | ||
await mkdir(join(process.cwd(), EDGE_HANDLER_DIR), { recursive: true }) | ||
import type { EdgeFunctionDefinition as NextDefinition } from 'next/dist/build/webpack/plugins/middleware-plugin.js' | ||
import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises' | ||
import { dirname, join, relative, resolve } from 'node:path' | ||
import { getMiddlewareManifest } from '../config.js' | ||
import { | ||
EDGE_FUNCTIONS_DIR, | ||
EDGE_HANDLER_NAME, | ||
PLUGIN_DIR, | ||
PLUGIN_NAME, | ||
PLUGIN_VERSION, | ||
} from '../constants.js' | ||
|
||
interface NetlifyManifest { | ||
version: 1 | ||
functions: NetlifyDefinition[] | ||
} | ||
|
||
type NetlifyDefinition = | ||
| { | ||
function: string | ||
name?: string | ||
path: string | ||
cache?: 'manual' | ||
generator: string | ||
} | ||
| { | ||
function: string | ||
name?: string | ||
pattern: string | ||
cache?: 'manual' | ||
generator: string | ||
} | ||
|
||
const getHandlerName = ({ name }: NextDefinition) => | ||
EDGE_HANDLER_NAME.replace('{{name}}', name.replace(/\W/g, '-')) | ||
|
||
const buildHandlerDefinitions = ( | ||
{ name: definitionName, matchers, page }: NextDefinition, | ||
handlerName: string, | ||
): NetlifyDefinition[] => { | ||
return definitionName === 'middleware' | ||
? [ | ||
{ | ||
function: handlerName, | ||
name: 'Next.js Middleware Handler', | ||
path: '/*', | ||
generator: `${PLUGIN_NAME}@${PLUGIN_VERSION}`, | ||
} as any, | ||
] | ||
: matchers.map((matcher) => ({ | ||
function: handlerName, | ||
name: `Next.js Edge Handler: ${page}`, | ||
pattern: matcher.regexp, | ||
cache: 'manual', | ||
generator: `${PLUGIN_NAME}@${PLUGIN_VERSION}`, | ||
})) | ||
} | ||
|
||
const copyHandlerDependencies = async ( | ||
{ name: definitionName, files }: NextDefinition, | ||
handlerName: string, | ||
) => { | ||
await Promise.all( | ||
files.map(async (file) => { | ||
const srcDir = join(process.cwd(), '.next/standalone/.next') | ||
const destDir = join(process.cwd(), EDGE_FUNCTIONS_DIR, handlerName) | ||
|
||
if (file === `server/${definitionName}.js`) { | ||
const entrypoint = await readFile(join(srcDir, file), 'utf8') | ||
// const exports = `` | ||
const exports = ` | ||
export default _ENTRIES["middleware_${definitionName}"].default; | ||
// export default () => { | ||
// console.log('here', _ENTRIES) | ||
// } | ||
` | ||
await mkdir(dirname(join(destDir, file)), { recursive: true }) | ||
await writeFile( | ||
join(destDir, file), | ||
` | ||
import './edge-runtime-webpack.js'; | ||
var _ENTRIES = {};\n`.concat(entrypoint, '\n', exports), | ||
) | ||
return | ||
} | ||
|
||
await cp(join(srcDir, file), join(destDir, file)) | ||
}), | ||
) | ||
} | ||
|
||
const writeHandlerFile = async ({ name: definitionName }: NextDefinition, handlerName: string) => { | ||
const handlerFile = resolve(EDGE_FUNCTIONS_DIR, handlerName, `${handlerName}.js`) | ||
const rel = relative(handlerFile, join(PLUGIN_DIR, 'dist/run/handlers/middleware.js')) | ||
await cp( | ||
join(PLUGIN_DIR, 'edge-runtime'), | ||
resolve(EDGE_FUNCTIONS_DIR, handlerName, 'edge-runtime'), | ||
{ | ||
recursive: true, | ||
}, | ||
) | ||
await writeFile( | ||
resolve(EDGE_FUNCTIONS_DIR, handlerName, `${handlerName}.js`), | ||
`import {handleMiddleware} from './edge-runtime/middleware.ts'; | ||
import handler from './server/${definitionName}.js'; | ||
export default (req, context) => handleMiddleware(req, context, handler); | ||
export const config = {path: "/*"}`, | ||
) | ||
} | ||
|
||
const writeEdgeManifest = async (manifest: NetlifyManifest) => { | ||
await mkdir(resolve(EDGE_FUNCTIONS_DIR), { recursive: true }) | ||
await writeFile(resolve(EDGE_FUNCTIONS_DIR, 'manifest.json'), JSON.stringify(manifest, null, 2)) | ||
} | ||
|
||
export const createEdgeHandlers = async () => { | ||
await rm(EDGE_FUNCTIONS_DIR, { recursive: true, force: true }) | ||
|
||
const nextManifest = await getMiddlewareManifest() | ||
const nextDefinitions = [ | ||
...Object.values(nextManifest.middleware), | ||
// ...Object.values(nextManifest.functions) | ||
] | ||
const netlifyManifest: NetlifyManifest = { | ||
version: 1, | ||
functions: await nextDefinitions.reduce( | ||
async (netlifyDefinitions: Promise<NetlifyDefinition[]>, nextDefinition: NextDefinition) => { | ||
const handlerName = getHandlerName(nextDefinition) | ||
await copyHandlerDependencies(nextDefinition, handlerName) | ||
await writeHandlerFile(nextDefinition, handlerName) | ||
return [ | ||
...(await netlifyDefinitions), | ||
...buildHandlerDefinitions(nextDefinition, handlerName), | ||
] | ||
}, | ||
Promise.resolve([]), | ||
), | ||
} | ||
|
||
await writeEdgeManifest(netlifyManifest) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export const metadata = { | ||
title: 'Simple Next App', | ||
description: 'Description for Simple Next App', | ||
} | ||
|
||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<body>{children}</body> | ||
</html> | ||
) | ||
} |
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,7 @@ | ||
export default function Home() { | ||
return ( | ||
<main> | ||
<h1>Other</h1> | ||
</main> | ||
) | ||
} |
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,7 @@ | ||
export default function Home() { | ||
return ( | ||
<main> | ||
<h1>Home</h1> | ||
</main> | ||
) | ||
} |
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,10 @@ | ||
import { NextResponse } from 'next/server' | ||
import type { NextRequest } from 'next/server' | ||
|
||
export function middleware(request: NextRequest) { | ||
return NextResponse.redirect(new URL('/other', request.url)) | ||
} | ||
|
||
export const config = { | ||
matcher: '/test', | ||
} |
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,9 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
output: 'standalone', | ||
eslint: { | ||
ignoreDuringBuilds: true, | ||
}, | ||
} | ||
|
||
module.exports = nextConfig |
Oops, something went wrong.