我有一个NextJS应用程序,它托管一个从Supabase获取数据的ISR页面。有一个中间件在呈现页面之前记录页面访问。
export async function middleware(
request: NextRequest,
fetchEvent: NextFetchEvent
) {
console.log('request.nextUrl.pathname', request.nextUrl.pathname);
if (request.nextUrl.pathname.split('/').length === 2) {
return linkVisitMiddleware(request, fetchEvent);
}
}
中间件被调用2 - 3次的问题(不知道为什么这些数字会波动)
上面的日志将在服务器上打印以下内容:
request.nextUrl.pathname /slug
request.nextUrl.pathname /slug
request.nextUrl.pathname /slug
奇怪的是,这只发生在生产中(next start
)。在本地(next serve
),它按预期运行一次。
我看到了几个关于reactStrictMode
的提及,但这没有帮助:(
编辑:
在NextJS13.1.1
,13.1.6
&13.3.0
经过几个小时的调试,我找到了问题所在。
ISR页面正在使用回退策略作为{fallback: true}
,因此,它尝试请求HTML页面,如果不可用,它再次访问相同的路由来获取数据。
import { linksMiddleware } from 'middleware/links';
import { NextFetchEvent, NextRequest, NextResponse } from 'next/server';
export async function middleware(
request: NextRequest,
fetchEvent: NextFetchEvent
) {
// These methods are used when accessing locale routes, so we discard them
if (request.method === 'OPTIONS' || request.method === 'HEAD') {
return NextResponse.next();
}
//Capture URL locale (if any) and id. For example: /ar/random-id or /random-id
const pathParams = request.nextUrl.pathname.split('/');
if (pathParams.length === 2 && isDataRequest(request)) {
// This means that we are accessing the entity homepage
return linksMiddleware(request, fetchEvent, 'entity');
}
return NextResponse.next();
}
export const config = {
matcher: [
// This is to prevent the middleware from running on the API routes and during development
'/((?!api|_next/static|_next/image|favicon.ico|favicon.svg).*)',
],
};
/**
* Check if the request is a data request for cases of fallback pages
* This header is absent in the initial request
*/
const isDataRequest = (request: NextRequest): boolean =>
request.headers.get('x-nextjs-data') === '1' ||
// The header is absent in development mode since there's no fallback logic (SSR-like)
process.env.NODE_ENV === 'development';
我还添加了一个检查HTTP方法的区域设置路由的情况,不包括OPTIONS
和HEAD
。