diff --git a/edge-runtime/shim/index.js b/edge-runtime/shim/index.js index 87340e6520..423c9dd3f6 100644 --- a/edge-runtime/shim/index.js +++ b/edge-runtime/shim/index.js @@ -36,3 +36,8 @@ globalThis.require = function nextRuntimeMinimalRequireShim(name) { } var _ENTRIES = {} +try { + // turbopack builds use self._ENTRIES not globalThis._ENTRIES + // so making sure both points to same object + self._ENTRIES = _ENTRIES +} catch {} diff --git a/src/build/content/server.ts b/src/build/content/server.ts index ad05a18e78..40e15663f3 100644 --- a/src/build/content/server.ts +++ b/src/build/content/server.ts @@ -105,6 +105,7 @@ export const copyNextServerCode = async (ctx: PluginContext): Promise => { `server/*`, `server/chunks/**/*`, `server/edge-chunks/**/*`, + `server/edge/chunks/**/*`, `server/+(app|pages)/**/*.js`, ], { diff --git a/src/build/functions/edge.ts b/src/build/functions/edge.ts index 1cf4554a0f..af6405b57c 100644 --- a/src/build/functions/edge.ts +++ b/src/build/functions/edge.ts @@ -150,10 +150,15 @@ const copyHandlerDependencies = async ( const entrypoint = await readFile(join(srcDir, file), 'utf8') parts.push(`;// Concatenated file: ${file} \n`, entrypoint) } - const exports = `const middlewareEntryKey = Object.keys(_ENTRIES).find(entryKey => entryKey.startsWith("middleware_${name}")); export default _ENTRIES[middlewareEntryKey].default;` + parts.push( + `const middlewareEntryKey = Object.keys(_ENTRIES).find(entryKey => entryKey.startsWith("middleware_${name}"));`, + // turbopack entries are promises so we await here to get actual entry + // non-turbopack entries are already resolved, so await does not change anything + `export default await _ENTRIES[middlewareEntryKey].default;`, + ) await mkdir(dirname(outputFile), { recursive: true }) - await writeFile(outputFile, [...parts, exports].join('\n')) + await writeFile(outputFile, parts.join('\n')) } const createEdgeHandler = async (ctx: PluginContext, definition: NextDefinition): Promise => { diff --git a/tests/fixtures/hello-world-turbopack/app/edge-page/page.js b/tests/fixtures/hello-world-turbopack/app/edge-page/page.js new file mode 100644 index 0000000000..53e742e33a --- /dev/null +++ b/tests/fixtures/hello-world-turbopack/app/edge-page/page.js @@ -0,0 +1,8 @@ +import { connection } from 'next/server' + +export const runtime = 'edge' + +export default async function Page() { + await connection() + return

Hello, Next.js!

+} diff --git a/tests/fixtures/hello-world-turbopack/app/page.js b/tests/fixtures/hello-world-turbopack/app/page.js index 6baa6ade86..e3dc3a1b9e 100644 --- a/tests/fixtures/hello-world-turbopack/app/page.js +++ b/tests/fixtures/hello-world-turbopack/app/page.js @@ -1,3 +1,6 @@ -export default function Page() { +import { connection } from 'next/server' + +export default async function Page() { + await connection() return

Hello, Next.js!

} diff --git a/tests/fixtures/hello-world-turbopack/middleware.ts b/tests/fixtures/hello-world-turbopack/middleware.ts new file mode 100644 index 0000000000..a2f7976a78 --- /dev/null +++ b/tests/fixtures/hello-world-turbopack/middleware.ts @@ -0,0 +1,12 @@ +import type { NextRequest } from 'next/server' +import { NextResponse } from 'next/server' + +export function middleware(request: NextRequest) { + return NextResponse.json({ + message: `Hello from middleware at ${request.nextUrl.pathname}`, + }) +} + +export const config = { + matcher: '/middleware/:path*', +} diff --git a/tests/integration/hello-world-turbopack.test.ts b/tests/integration/hello-world-turbopack.test.ts index 803a714b54..d7681179a3 100644 --- a/tests/integration/hello-world-turbopack.test.ts +++ b/tests/integration/hello-world-turbopack.test.ts @@ -3,9 +3,9 @@ import { getLogger } from 'lambda-local' import { HttpResponse, http, passthrough } from 'msw' import { setupServer } from 'msw/node' import { v4 } from 'uuid' -import { afterAll, afterEach, beforeAll, beforeEach, expect, test, vi } from 'vitest' +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' import { type FixtureTestContext } from '../utils/contexts.js' -import { createFixture, invokeFunction, runPlugin } from '../utils/fixture.js' +import { createFixture, invokeEdgeFunction, invokeFunction, runPlugin } from '../utils/fixture.js' import { generateRandomObjectID, startMockBlobStore } from '../utils/helpers.js' import { nextVersionSatisfies } from '../utils/next-version-helpers.mjs' @@ -63,15 +63,44 @@ afterEach(() => { // https://github.com/vercel/next.js/pull/77808 makes turbopack builds no longer gated only to canaries // allowing to run this test on both stable and canary versions of Next.js -test.skipIf(!nextVersionSatisfies('>=15.3.0-canary.43'))( +describe.skipIf(!nextVersionSatisfies('>=15.3.0-canary.43'))( 'Test that the hello-world-turbopack next app is working', - async (ctx) => { - await createFixture('hello-world-turbopack', ctx) - await runPlugin(ctx) - - // test the function call - const home = await invokeFunction(ctx) - expect(home.statusCode).toBe(200) - expect(load(home.body)('h1').text()).toBe('Hello, Next.js!') + () => { + test('regular page is working', async (ctx) => { + await createFixture('hello-world-turbopack', ctx) + await runPlugin(ctx) + + // test the function call + const home = await invokeFunction(ctx) + expect(home.statusCode).toBe(200) + expect(load(home.body)('h1').text()).toBe('Hello, Next.js!') + }) + + test('edge page is working', async (ctx) => { + await createFixture('hello-world-turbopack', ctx) + await runPlugin(ctx) + + // test the function call + const home = await invokeFunction(ctx, { url: '/edge-page' }) + expect(home.statusCode).toBe(200) + expect(load(home.body)('h1').text()).toBe('Hello, Next.js!') + }) + + test('middleware is working', async (ctx) => { + await createFixture('hello-world-turbopack', ctx) + await runPlugin(ctx) + + const pathname = '/middleware/test' + + const response = await invokeEdgeFunction(ctx, { + functions: ['___netlify-edge-handler-middleware'], + url: pathname, + }) + + expect(response.status).toBe(200) + expect(await response.json()).toEqual({ + message: `Hello from middleware at ${pathname}`, + }) + }) }, )