Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8c86b77

Browse files
authored
fix: fail build/deploy when using not yet unsupported Node.js Midleware (#3016)
1 parent 45b43e6 commit 8c86b77

File tree

8 files changed

+105
-3
lines changed

8 files changed

+105
-3
lines changed

‎src/build/content/server.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { trace } from '@opentelemetry/api'
1717
import { wrapTracer } from '@opentelemetry/api/experimental'
1818
import glob from 'fast-glob'
1919
import type { MiddlewareManifest } from 'next/dist/build/webpack/plugins/middleware-plugin.js'
20+
import type { FunctionsConfigManifest } from 'next-with-cache-handler-v2/dist/build/index.js'
2021
import { prerelease, satisfies, lt as semverLowerThan, lte as semverLowerThanOrEqual } from 'semver'
2122

2223
import type { RunConfig } from '../../run/config.js'
@@ -131,6 +132,10 @@ export const copyNextServerCode = async (ctx: PluginContext): Promise<void> => {
131132
return
132133
}
133134

135+
if (path === 'server/functions-config-manifest.json') {
136+
await verifyFunctionsConfigManifest(join(srcDir, path))
137+
}
138+
134139
await cp(srcPath, destPath, { recursive: true, force: true })
135140
}),
136141
)
@@ -376,6 +381,22 @@ const replaceMiddlewareManifest = async (sourcePath: string, destPath: string) =
376381
await writeFile(destPath, newData)
377382
}
378383

384+
const verifyFunctionsConfigManifest = async (sourcePath: string) => {
385+
const data = await readFile(sourcePath, 'utf8')
386+
const manifest = JSON.parse(data) as FunctionsConfigManifest
387+
388+
// https://github.com/vercel/next.js/blob/8367faedd61501025299e92d43a28393c7bb50e2/packages/next/src/build/index.ts#L2465
389+
// Node.js Middleware has hardcoded /_middleware path
390+
if (manifest.functions['/_middleware']) {
391+
throw new Error(
392+
'Node.js middleware is not yet supported.\n\n' +
393+
'Future @netlify/plugin-nextjs release will support node middleware with following limitations:\n' +
394+
' - usage of C++ Addons (https://nodejs.org/api/addons.html) not supported (for example `bcrypt` npm module will not be supported, but `bcryptjs` will be supported),\n' +
395+
' - usage of Filesystem (https://nodejs.org/api/fs.html) not supported.',
396+
)
397+
}
398+
}
399+
379400
export const verifyHandlerDirStructure = async (ctx: PluginContext) => {
380401
const { nextConfig } = JSON.parse(
381402
await readFile(join(ctx.serverHandlerDir, RUN_CONFIG_FILE), 'utf-8'),
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const metadata = {
2+
title: 'Simple Next App',
3+
description: 'Description for Simple Next App',
4+
}
5+
6+
export default function RootLayout({ children }) {
7+
return (
8+
<html lang="en">
9+
<body>{children}</body>
10+
</html>
11+
)
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Home() {
2+
return (
3+
<main>
4+
<h1>Home</h1>
5+
</main>
6+
)
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { NextRequest } from 'next/server'
2+
3+
export async function middleware(request: NextRequest) {
4+
console.log('Node.js Middleware request:', request.method, request.nextUrl.pathname)
5+
}
6+
7+
export const config = {
8+
runtime: 'nodejs',
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/** @type {import('next').NextConfig} */
2+
const nextConfig = {
3+
output: 'standalone',
4+
eslint: {
5+
ignoreDuringBuilds: true,
6+
},
7+
experimental: {
8+
nodeMiddleware: true,
9+
},
10+
}
11+
12+
module.exports = nextConfig
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "middleware-node",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"postinstall": "next build",
7+
"dev": "next dev",
8+
"build": "next build"
9+
},
10+
"dependencies": {
11+
"next": "latest",
12+
"react": "18.2.0",
13+
"react-dom": "18.2.0"
14+
},
15+
"test": {
16+
"dependencies": {
17+
"next": ">=15.2.0"
18+
}
19+
}
20+
}

‎tests/integration/edge-handler.test.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { type FixtureTestContext } from '../utils/contexts.js'
44
import { createFixture, invokeEdgeFunction, runPlugin } from '../utils/fixture.js'
55
import { generateRandomObjectID, startMockBlobStore } from '../utils/helpers.js'
66
import { LocalServer } from '../utils/local-server.js'
7+
import { nextVersionSatisfies } from '../utils/next-version-helpers.mjs'
78

89
beforeEach<FixtureTestContext>(async (ctx) => {
910
// set for each test a new deployID and siteID
@@ -626,3 +627,23 @@ describe('page router', () => {
626627
expect(bodyFr.nextUrlLocale).toBe('fr')
627628
})
628629
})
630+
631+
test.skipIf(!nextVersionSatisfies('>=15.2.0'))<FixtureTestContext>(
632+
'should throw an Not Supported error when node middleware is used',
633+
async (ctx) => {
634+
await createFixture('middleware-node', ctx)
635+
636+
const runPluginPromise = runPlugin(ctx)
637+
638+
await expect(runPluginPromise).rejects.toThrow('Node.js middleware is not yet supported.')
639+
await expect(runPluginPromise).rejects.toThrow(
640+
'Future @netlify/plugin-nextjs release will support node middleware with following limitations:',
641+
)
642+
await expect(runPluginPromise).rejects.toThrow(
643+
' - usage of C++ Addons (https://nodejs.org/api/addons.html) not supported (for example `bcrypt` npm module will not be supported, but `bcryptjs` will be supported)',
644+
)
645+
await expect(runPluginPromise).rejects.toThrow(
646+
' - usage of Filesystem (https://nodejs.org/api/fs.html) not supported',
647+
)
648+
},
649+
)

‎tests/utils/next-version-helpers.mjs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ export function isNextCanary() {
3333
export function shouldHaveAppRouterNotFoundInPrerenderManifest() {
3434
// https://github.com/vercel/next.js/pull/82199
3535

36-
// The canary versions are out of band, as there stable/latest patch versions higher than base of canary versions
37-
// and change was not backported to stable versions
38-
return nextVersionSatisfies('>=15.4.2-canary.33')&&isNextCanary()
36+
// The canary versions are out of band, as there stable/latest patch versions higher than base of canary versions without
37+
// the change included
38+
return nextVersionSatisfies(isNextCanary() ? '>=15.4.2-canary.33' : '>=15.5.0')
3939
}
4040

4141
/**

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /