Revert "support runtime: edge
in api endpoints" (#37337)
Revert "support `runtime: edge` in api endpoints (#36947)"
This reverts commit 3d1a287207
.
This commit is contained in:
parent
3d1a287207
commit
ed0b580fc4
12 changed files with 35 additions and 271 deletions
|
@ -164,15 +164,6 @@ export function getEdgeServerEntry(opts: {
|
|||
return `next-middleware-loader?${stringify(loaderParams)}!`
|
||||
}
|
||||
|
||||
if (opts.page.startsWith('/api/')) {
|
||||
const loaderParams: MiddlewareLoaderOptions = {
|
||||
absolutePagePath: opts.absolutePagePath,
|
||||
page: opts.page,
|
||||
}
|
||||
|
||||
return `next-edge-function-loader?${stringify(loaderParams)}!`
|
||||
}
|
||||
|
||||
const loaderParams: MiddlewareSSRLoaderQuery = {
|
||||
absolute500Path: opts.pages['/500'] || '',
|
||||
absoluteAppPath: opts.pages['/_app'],
|
||||
|
@ -418,9 +409,7 @@ export function runDependingOnPageType<T>(params: {
|
|||
if (params.page === MIDDLEWARE_FILE) {
|
||||
return [params.onEdgeServer()]
|
||||
} else if (params.page.match(API_ROUTE)) {
|
||||
return params.pageRuntime === 'edge'
|
||||
? [params.onEdgeServer()]
|
||||
: [params.onServer()]
|
||||
return [params.onServer()]
|
||||
} else if (params.page === '/_document') {
|
||||
return [params.onServer()]
|
||||
} else if (
|
||||
|
|
|
@ -94,6 +94,7 @@ import {
|
|||
getUnresolvedModuleFromError,
|
||||
copyTracedFiles,
|
||||
isReservedPage,
|
||||
isCustomErrorPage,
|
||||
isServerComponentPage,
|
||||
} from './utils'
|
||||
import getBaseWebpackConfig from './webpack-config'
|
||||
|
@ -1254,7 +1255,10 @@ export default async function build(
|
|||
isHybridAmp,
|
||||
ssgPageRoutes,
|
||||
initialRevalidateSeconds: false,
|
||||
runtime: pageRuntime,
|
||||
runtime:
|
||||
!isReservedPage(page) && !isCustomErrorPage(page)
|
||||
? pageRuntime
|
||||
: undefined,
|
||||
pageDuration: undefined,
|
||||
ssgPageDurations: undefined,
|
||||
})
|
||||
|
|
|
@ -1232,7 +1232,6 @@ export default async function getBaseWebpackConfig(
|
|||
'next-flight-client-entry-loader',
|
||||
'noop-loader',
|
||||
'next-middleware-loader',
|
||||
'next-edge-function-loader',
|
||||
'next-middleware-ssr-loader',
|
||||
'next-middleware-wasm-loader',
|
||||
'next-app-loader',
|
||||
|
|
|
@ -7,7 +7,6 @@ import { webpack5 } from 'next/dist/compiled/webpack/webpack'
|
|||
export function getModuleBuildInfo(webpackModule: webpack5.Module) {
|
||||
return webpackModule.buildInfo as {
|
||||
nextEdgeMiddleware?: EdgeMiddlewareMeta
|
||||
nextEdgeApiFunction?: EdgeMiddlewareMeta
|
||||
nextEdgeSSR?: EdgeSSRMeta
|
||||
nextUsedEnvVars?: Set<string>
|
||||
nextWasmMiddlewareBinding?: WasmBinding
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import { getModuleBuildInfo } from './get-module-build-info'
|
||||
import { stringifyRequest } from '../stringify-request'
|
||||
|
||||
export type EdgeFunctionLoaderOptions = {
|
||||
absolutePagePath: string
|
||||
page: string
|
||||
}
|
||||
|
||||
export default function middlewareLoader(this: any) {
|
||||
const { absolutePagePath, page }: EdgeFunctionLoaderOptions =
|
||||
this.getOptions()
|
||||
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
|
||||
const buildInfo = getModuleBuildInfo(this._module)
|
||||
buildInfo.nextEdgeApiFunction = {
|
||||
page: page || '/',
|
||||
}
|
||||
|
||||
return `
|
||||
import { adapter } from 'next/dist/server/web/adapter'
|
||||
|
||||
// The condition is true when the "process" module is provided
|
||||
if (process !== global.process) {
|
||||
// prefer local process but global.process has correct "env"
|
||||
process.env = global.process.env;
|
||||
global.process = process;
|
||||
}
|
||||
|
||||
var mod = require(${stringifiedPagePath})
|
||||
var handler = mod.middleware || mod.default;
|
||||
|
||||
if (typeof handler !== 'function') {
|
||||
throw new Error('The Edge Function "pages${page}" must export a \`default\` function');
|
||||
}
|
||||
|
||||
export default function (opts) {
|
||||
return adapter({
|
||||
...opts,
|
||||
page: ${JSON.stringify(page)},
|
||||
handler,
|
||||
})
|
||||
}
|
||||
`
|
||||
}
|
|
@ -14,26 +14,24 @@ import {
|
|||
NEXT_CLIENT_SSR_ENTRY_SUFFIX,
|
||||
} from '../../../shared/lib/constants'
|
||||
|
||||
interface EdgeFunctionDefinition {
|
||||
env: string[]
|
||||
files: string[]
|
||||
name: string
|
||||
page: string
|
||||
regexp: string
|
||||
wasm?: WasmBinding[]
|
||||
}
|
||||
|
||||
export interface MiddlewareManifest {
|
||||
version: 1
|
||||
sortedMiddleware: string[]
|
||||
clientInfo: [location: string, isSSR: boolean][]
|
||||
middleware: { [page: string]: EdgeFunctionDefinition }
|
||||
functions: { [page: string]: EdgeFunctionDefinition }
|
||||
middleware: {
|
||||
[page: string]: {
|
||||
env: string[]
|
||||
files: string[]
|
||||
name: string
|
||||
page: string
|
||||
regexp: string
|
||||
wasm?: WasmBinding[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface EntryMetadata {
|
||||
edgeMiddleware?: EdgeMiddlewareMeta
|
||||
edgeApiFunction?: EdgeMiddlewareMeta
|
||||
edgeSSR?: EdgeSSRMeta
|
||||
env: Set<string>
|
||||
wasmBindings: Set<WasmBinding>
|
||||
|
@ -44,7 +42,6 @@ const middlewareManifest: MiddlewareManifest = {
|
|||
sortedMiddleware: [],
|
||||
clientInfo: [],
|
||||
middleware: {},
|
||||
functions: {},
|
||||
version: 1,
|
||||
}
|
||||
|
||||
|
@ -313,8 +310,6 @@ function getExtractMetadata(params: {
|
|||
entryMetadata.edgeSSR = buildInfo.nextEdgeSSR
|
||||
} else if (buildInfo?.nextEdgeMiddleware) {
|
||||
entryMetadata.edgeMiddleware = buildInfo.nextEdgeMiddleware
|
||||
} else if (buildInfo?.nextEdgeApiFunction) {
|
||||
entryMetadata.edgeApiFunction = buildInfo.nextEdgeApiFunction
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -391,19 +386,16 @@ function getCreateAssets(params: {
|
|||
|
||||
// There should always be metadata for the entrypoint.
|
||||
const metadata = metadataByEntry.get(entrypoint.name)
|
||||
const page =
|
||||
metadata?.edgeMiddleware?.page ||
|
||||
metadata?.edgeSSR?.page ||
|
||||
metadata?.edgeApiFunction?.page
|
||||
const page = metadata?.edgeMiddleware?.page || metadata?.edgeSSR?.page
|
||||
if (!page) {
|
||||
continue
|
||||
}
|
||||
|
||||
const { namedRegex } = getNamedMiddlewareRegex(page, {
|
||||
catchAll: !metadata.edgeSSR && !metadata.edgeApiFunction,
|
||||
catchAll: !metadata.edgeSSR,
|
||||
})
|
||||
|
||||
const edgeFunctionDefinition: EdgeFunctionDefinition = {
|
||||
middlewareManifest.middleware[page] = {
|
||||
env: Array.from(metadata.env),
|
||||
files: getEntryFiles(entrypoint.getFiles(), metadata),
|
||||
name: entrypoint.name,
|
||||
|
@ -411,12 +403,6 @@ function getCreateAssets(params: {
|
|||
regexp: namedRegex,
|
||||
wasm: Array.from(metadata.wasmBindings),
|
||||
}
|
||||
|
||||
if (metadata.edgeApiFunction /* || metadata.edgeSSR */) {
|
||||
middlewareManifest.functions[page] = edgeFunctionDefinition
|
||||
} else {
|
||||
middlewareManifest.middleware[page] = edgeFunctionDefinition
|
||||
}
|
||||
}
|
||||
|
||||
middlewareManifest.sortedMiddleware = getSortedRoutes(
|
||||
|
|
|
@ -19,7 +19,7 @@ function requestToBodyStream(request: IncomingMessage): BodyStream {
|
|||
return transform.readable as unknown as ReadableStream<Uint8Array>
|
||||
}
|
||||
|
||||
export function bodyStreamToNodeStream(bodyStream: BodyStream): Readable {
|
||||
function bodyStreamToNodeStream(bodyStream: BodyStream): Readable {
|
||||
const reader = bodyStream.getReader()
|
||||
return Readable.from(
|
||||
(async function* () {
|
||||
|
|
|
@ -354,9 +354,7 @@ export default class DevServer extends Server {
|
|||
onClient: () => {},
|
||||
onServer: () => {},
|
||||
onEdgeServer: () => {
|
||||
if (!pageName.startsWith('/api/')) {
|
||||
routedMiddleware.push(pageName)
|
||||
}
|
||||
routedMiddleware.push(pageName)
|
||||
ssrMiddleware.add(pageName)
|
||||
},
|
||||
})
|
||||
|
|
|
@ -72,9 +72,9 @@ import { getCustomRoute } from './server-route-utils'
|
|||
import { urlQueryToSearchParams } from '../shared/lib/router/utils/querystring'
|
||||
import ResponseCache from '../server/response-cache'
|
||||
import { removeTrailingSlash } from '../shared/lib/router/utils/remove-trailing-slash'
|
||||
import { getNextPathnameInfo } from '../shared/lib/router/utils/get-next-pathname-info'
|
||||
import { clonableBodyForRequest } from './body-streams'
|
||||
import { getMiddlewareRegex } from '../shared/lib/router/utils/route-regex'
|
||||
import { bodyStreamToNodeStream, clonableBodyForRequest } from './body-streams'
|
||||
import { getNextPathnameInfo } from '../shared/lib/router/utils/get-next-pathname-info'
|
||||
|
||||
export * from './base-server'
|
||||
|
||||
|
@ -540,19 +540,6 @@ export default class NextNodeServer extends BaseServer {
|
|||
page: string,
|
||||
builtPagePath: string
|
||||
): Promise<boolean> {
|
||||
const handledAsEdgeFunction = await this.runEdgeFunctionApiEndpoint({
|
||||
req,
|
||||
res,
|
||||
query,
|
||||
params,
|
||||
page,
|
||||
builtPagePath,
|
||||
})
|
||||
|
||||
if (handledAsEdgeFunction) {
|
||||
return true
|
||||
}
|
||||
|
||||
const pageModule = await require(builtPagePath)
|
||||
query = { ...query, ...params }
|
||||
|
||||
|
@ -1044,15 +1031,11 @@ export default class NextNodeServer extends BaseServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get information for the edge function located in the provided page
|
||||
* folder. If the edge function info can't be found it will throw
|
||||
* Get information for the middleware located in the provided page
|
||||
* folder. If the middleware info can't be found it will throw
|
||||
* an error.
|
||||
*/
|
||||
protected getEdgeFunctionInfo(params: {
|
||||
page: string
|
||||
/** Whether we should look for a middleware or not */
|
||||
middleware: boolean
|
||||
}) {
|
||||
protected getMiddlewareInfo(page: string) {
|
||||
const manifest: MiddlewareManifest = require(join(
|
||||
this.serverDistDir,
|
||||
MIDDLEWARE_MANIFEST
|
||||
|
@ -1061,14 +1044,12 @@ export default class NextNodeServer extends BaseServer {
|
|||
let foundPage: string
|
||||
|
||||
try {
|
||||
foundPage = denormalizePagePath(normalizePagePath(params.page))
|
||||
foundPage = denormalizePagePath(normalizePagePath(page))
|
||||
} catch (err) {
|
||||
throw pageNotFoundError(params.page)
|
||||
throw pageNotFoundError(page)
|
||||
}
|
||||
|
||||
let pageInfo = params.middleware
|
||||
? manifest.middleware[foundPage]
|
||||
: manifest.functions[foundPage]
|
||||
let pageInfo = manifest.middleware[foundPage]
|
||||
if (!pageInfo) {
|
||||
throw pageNotFoundError(foundPage)
|
||||
}
|
||||
|
@ -1094,10 +1075,7 @@ export default class NextNodeServer extends BaseServer {
|
|||
_isSSR?: boolean
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
return (
|
||||
this.getEdgeFunctionInfo({ page: pathname, middleware: true }).paths
|
||||
.length > 0
|
||||
)
|
||||
return this.getMiddlewareInfo(pathname).paths.length > 0
|
||||
} catch (_) {}
|
||||
|
||||
return false
|
||||
|
@ -1164,10 +1142,7 @@ export default class NextNodeServer extends BaseServer {
|
|||
}
|
||||
|
||||
await this.ensureMiddleware(middleware.page, middleware.ssr)
|
||||
const middlewareInfo = this.getEdgeFunctionInfo({
|
||||
page: middleware.page,
|
||||
middleware: true,
|
||||
})
|
||||
const middlewareInfo = this.getMiddlewareInfo(middleware.page)
|
||||
|
||||
result = await run({
|
||||
name: middlewareInfo.name,
|
||||
|
@ -1436,80 +1411,4 @@ export default class NextNodeServer extends BaseServer {
|
|||
this.warnIfQueryParametersWereDeleted = () => {}
|
||||
}
|
||||
}
|
||||
|
||||
private async runEdgeFunctionApiEndpoint(params: {
|
||||
req: NodeNextRequest
|
||||
res: NodeNextResponse
|
||||
query: ParsedUrlQuery
|
||||
params: Params | false
|
||||
page: string
|
||||
builtPagePath: string
|
||||
}): Promise<boolean> {
|
||||
let middlewareInfo: ReturnType<typeof this.getEdgeFunctionInfo> | undefined
|
||||
|
||||
try {
|
||||
middlewareInfo = this.getEdgeFunctionInfo({
|
||||
page: params.page,
|
||||
middleware: false,
|
||||
})
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
|
||||
// For middleware to "fetch" we must always provide an absolute URL
|
||||
const url = getRequestMeta(params.req, '__NEXT_INIT_URL')!
|
||||
if (!url.startsWith('http')) {
|
||||
throw new Error(
|
||||
'To use middleware you must provide a `hostname` and `port` to the Next.js Server'
|
||||
)
|
||||
}
|
||||
|
||||
const result = await run({
|
||||
name: middlewareInfo.name,
|
||||
paths: middlewareInfo.paths,
|
||||
env: middlewareInfo.env,
|
||||
wasm: middlewareInfo.wasm,
|
||||
request: {
|
||||
headers: params.req.headers,
|
||||
method: params.req.method,
|
||||
nextConfig: {
|
||||
basePath: this.nextConfig.basePath,
|
||||
i18n: this.nextConfig.i18n,
|
||||
trailingSlash: this.nextConfig.trailingSlash,
|
||||
},
|
||||
url,
|
||||
page: {
|
||||
name: params.page,
|
||||
...(params.params && { params: params.params }),
|
||||
},
|
||||
// TODO(gal): complete body
|
||||
// body: originalBody?.cloneBodyStream(),
|
||||
},
|
||||
useCache: !this.nextConfig.experimental.runtime,
|
||||
onWarning: (_warning: Error) => {
|
||||
// if (params.onWarning) {
|
||||
// warning.message += ` "./${middlewareInfo.name}"`
|
||||
// params.onWarning(warning)
|
||||
// }
|
||||
},
|
||||
})
|
||||
|
||||
params.res.statusCode = result.response.status
|
||||
params.res.statusMessage = result.response.statusText
|
||||
|
||||
result.response.headers.forEach((value, key) => {
|
||||
params.res.appendHeader(key, value)
|
||||
})
|
||||
|
||||
if (result.response.body) {
|
||||
// TODO(gal): not sure that we always need to stream
|
||||
bodyStreamToNodeStream(result.response.body).pipe(
|
||||
params.res.originalResponse
|
||||
)
|
||||
} else {
|
||||
params.res.originalResponse.end()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
export default (req) => {
|
||||
return new Response(`Hello from ${req.url}`)
|
||||
}
|
||||
|
||||
export const config = {
|
||||
runtime: 'edge',
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export default (req, res) => {
|
||||
res.send('Hello, world')
|
||||
}
|
|
@ -12,7 +12,6 @@ import {
|
|||
renderViaHTTP,
|
||||
waitFor,
|
||||
} from 'next-test-utils'
|
||||
import { readJson } from 'fs-extra'
|
||||
|
||||
const appDir = join(__dirname, '../switchable-runtime')
|
||||
|
||||
|
@ -175,31 +174,6 @@ describe('Switchable runtime (prod)', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('should build /api/hello as an api route with edge runtime', async () => {
|
||||
const response = await fetchViaHTTP(context.appPort, '/api/hello')
|
||||
const text = await response.text()
|
||||
expect(text).toMatch(/Hello from .+\/api\/hello/)
|
||||
|
||||
const manifest = await readJson(
|
||||
join(context.appDir, '.next/server/middleware-manifest.json')
|
||||
)
|
||||
expect(manifest).toMatchObject({
|
||||
functions: {
|
||||
'/api/hello': {
|
||||
env: [],
|
||||
files: [
|
||||
'server/edge-runtime-webpack.js',
|
||||
'server/pages/api/hello.js',
|
||||
],
|
||||
name: 'pages/api/hello',
|
||||
page: '/api/hello',
|
||||
regexp: '^/api/hello$',
|
||||
wasm: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('should display correct tree view with page types in terminal', async () => {
|
||||
const stdoutLines = splitLines(context.stdout).filter((line) =>
|
||||
/^[┌├└/]/.test(line)
|
||||
|
@ -207,8 +181,6 @@ describe('Switchable runtime (prod)', () => {
|
|||
const expectedOutputLines = splitLines(`
|
||||
┌ /_app
|
||||
├ ○ /404
|
||||
├ ℇ /api/hello
|
||||
├ λ /api/node
|
||||
├ ℇ /edge
|
||||
├ ℇ /edge-rsc
|
||||
├ ○ /node
|
||||
|
@ -220,16 +192,12 @@ describe('Switchable runtime (prod)', () => {
|
|||
├ λ /node-ssr
|
||||
└ ○ /static
|
||||
`)
|
||||
|
||||
const mappedOutputLines = expectedOutputLines.map((_line, index) => {
|
||||
/** @type {string} */
|
||||
const str = stdoutLines[index]
|
||||
const beginningOfPath = str.indexOf('/')
|
||||
const endOfPath = str.indexOf(' ', beginningOfPath)
|
||||
return str.slice(0, endOfPath)
|
||||
const isMatched = expectedOutputLines.every((line, index) => {
|
||||
const matched = stdoutLines[index].startsWith(line)
|
||||
return matched
|
||||
})
|
||||
|
||||
expect(mappedOutputLines).toEqual(expectedOutputLines)
|
||||
expect(isMatched).toBe(true)
|
||||
})
|
||||
|
||||
it('should prefetch data for static pages', async () => {
|
||||
|
@ -371,29 +339,4 @@ describe('Switchable runtime (dev)', () => {
|
|||
'This is a static RSC page.'
|
||||
)
|
||||
})
|
||||
|
||||
it('should build /api/hello as an api route with edge runtime', async () => {
|
||||
const response = await fetchViaHTTP(context.appPort, '/api/hello')
|
||||
const text = await response.text()
|
||||
expect(text).toMatch(/Hello from .+\/api\/hello/)
|
||||
|
||||
const manifest = await readJson(
|
||||
join(context.appDir, '.next/server/middleware-manifest.json')
|
||||
)
|
||||
expect(manifest).toMatchObject({
|
||||
functions: {
|
||||
'/api/hello': {
|
||||
env: [],
|
||||
files: [
|
||||
'server/edge-runtime-webpack.js',
|
||||
'server/pages/api/hello.js',
|
||||
],
|
||||
name: 'pages/api/hello',
|
||||
page: '/api/hello',
|
||||
regexp: '^/api/hello$',
|
||||
wasm: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue