Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 19 additions & 30 deletions packages/next/src/build/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
MiddlewareMatcher,
PageStaticInfo,
} from './analysis/get-page-static-info'
import * as Log from './output/log'
import type { LoadedEnvFiles } from '@next/env'
import type { AppLoaderOptions } from './webpack/loaders/next-app-loader'

Expand Down Expand Up @@ -533,13 +532,9 @@ export function runDependingOnPageType<T>(params: {
}

if (isMiddlewareFile(params.page)) {
if (params.pageRuntime === 'nodejs') {
params.onServer()
return
} else {
params.onEdgeServer()
return
}
// Always route middleware to Node.js server
params.onServer()
return
}

if (isAPIRoute(params.page)) {
Expand Down Expand Up @@ -675,20 +670,12 @@ export async function createEntrypoints(

let pageRuntime = staticInfo?.runtime

if (
isMiddlewareFile(page) &&
!config.experimental.nodeMiddleware &&
pageRuntime === 'nodejs'
) {
Log.warn(
'nodejs runtime support for middleware requires experimental.nodeMiddleware be enabled in your next.config'
)
pageRuntime = 'edge'
}
// Allow middleware to run in Node.js context
// Removed runtime override to edge

runDependingOnPageType({
page,
pageRuntime: staticInfo.runtime,
pageRuntime: pageRuntime,
pageType: pagesType,
onClient: () => {
if (isServerComponent || isInsideAppDir) {
Expand Down Expand Up @@ -729,19 +716,21 @@ export async function createEntrypoints(
isDev: false,
})
} else if (isMiddlewareFile(page)) {
server[serverBundlePath.replace('src/', '')] = getEdgeServerEntry({
...params,
rootDir,
absolutePagePath: absolutePagePath,
bundlePath: clientBundlePath,
isDev: false,
isServerComponent,
// Use middleware loader but compile for Node.js
const loaderParams: MiddlewareLoaderOptions = {
absolutePagePath,
page,
middleware: staticInfo?.middleware,
pagesType,
rootDir,
matchers: staticInfo.middleware?.matchers
? encodeToBase64(staticInfo.middleware.matchers)
: '',
preferredRegion: staticInfo.preferredRegion,
middlewareConfig: staticInfo.middleware,
})
middlewareConfig: encodeToBase64(staticInfo.middleware || {}),
}
server[serverBundlePath.replace('src/', '')] = {
import: `next-middleware-loader?${stringify(loaderParams)}!`,
layer: WEBPACK_LAYERS.apiNode,
}
} else if (isAPIRoute(page)) {
server[serverBundlePath] = [
getRouteLoaderEntry({
Expand Down
24 changes: 24 additions & 0 deletions packages/next/src/build/webpack/loaders/next-middleware-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,30 @@ export default async function middlewareLoader(this: any) {
middlewareConfig,
}

// Check if we're compiling for Node.js (apiNode layer)
const isNodeLayer = this._module?.layer === 'api-node'

if (isNodeLayer) {
// For Node.js layer, return a simple module that exports the middleware directly
return `
import * as _mod from ${JSON.stringify(pagePath)}

const mod = { ..._mod }
const handler = mod.middleware || mod.default

if (typeof handler !== 'function') {
throw new Error(
'The Middleware "${page}" must export a \`middleware\` or a \`default\` function'
)
}

// Export the middleware handler directly for Node.js context
export const middleware = handler
export const config = mod.config || {}
export default handler
`
}

return await loadEntrypoint('middleware', {
VAR_USERLAND: pagePath,
VAR_DEFINITION_PAGE: page,
Expand Down
5 changes: 3 additions & 2 deletions packages/next/src/build/webpack/plugins/middleware-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ function buildWebpackError({

function isInMiddlewareLayer(parser: webpack.javascript.JavascriptParser) {
const layer = parser.state.module?.layer
// Only check for edge runtime layers, not Node.js API layer
return layer === WEBPACK_LAYERS.middleware || layer === WEBPACK_LAYERS.apiEdge
}

Expand Down Expand Up @@ -866,9 +867,9 @@ export async function handleWebpackExternalForEdgeRuntime({
contextInfo: any
getResolve: () => any
}) {
// Allow Node.js modules in middleware when using Node.js runtime
if (
(contextInfo.issuerLayer === WEBPACK_LAYERS.middleware ||
contextInfo.issuerLayer === WEBPACK_LAYERS.apiEdge) &&
contextInfo.issuerLayer === WEBPACK_LAYERS.apiEdge &&
isNodeJsModule(request) &&
!supportedEdgePolyfills.has(request)
) {
Expand Down
5 changes: 1 addition & 4 deletions packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1444,10 +1444,7 @@ export default class NextNodeServer extends BaseServer<
}

private async loadNodeMiddleware() {
if (!this.nextConfig.experimental.nodeMiddleware) {
return
}

// Always load middleware as Node.js module
try {
const functionsConfig = this.renderOpts.dev
? {}
Expand Down
Loading