typescript - Το middleware του NextJS καλείται πολλές φορές κατά την πρόσβαση σε μια σελίδα ISR
Έχω μια εφαρμογή NextJS που φιλοξενεί μια σελίδα ISR που ανακτά δεδομένα από το Supabase. Υπάρχει ένα middleware που καταγράφει μια επίσκεψη σελίδας πριν την απόδοση της σελίδας.
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);
}
}
Το πρόβλημα είναι ότι το middleware καλείται 2 ή 3 φορές (δεν ξέρω γιατί αυτοί οι αριθμοί κυμαίνονται).
Η παραπάνω καταγραφή θα εμφανίσει τα εξής στον διακομιστή:
request.nextUrl.pathname /slug
request.nextUrl.pathname /slug
request.nextUrl.pathname /slug
Το παράξενο είναι ότι αυτό συμβαίνει μόνο στην παραγωγή (next start). Τοπικά (next serve), τρέχει μία φορά όπως αναμένεται.
Είδα μερικές αναφορές για το reactStrictMode, αλλά αυτό δεν βοήθησε :(
Επεξεργασία :
Δοκιμάστηκε σε NextJS 13.1.1, 13.1.6 & 13.3.0
Απάντηση #1
Μετά από ώρες αποσφαλμάτωσης, βρήκα τον ένοχο.
Η σελίδα ISR χρησιμοποιεί τη στρατηγική fallback ως {fallback: true} και λόγω αυτού, προσπαθεί να ζητήσει τη σελίδα HTML, και αν δεν είναι διαθέσιμη, επανέρχεται στην ίδια διαδρομή για να ανακτήσει τα δεδομένα.
Για να παρακάμψω αυτό, διαπίστωσα ότι το NextJS χρησιμοποιεί κεφαλίδες για να διακρίνει τον τύπο του αιτήματος. Ορίστε η λύση μου:
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.
