Closed10
[Next.js] basePath 利用時の nextUrl についてメモ

references
basePath
NextRequest.nextUrl

NextRequest interface
/**
* This class extends the [Web `Request` API](https://developer.mozilla.org/docs/Web/API/Request) with additional convenience methods.
*
* Read more: [Next.js Docs: `NextRequest`](https://nextjs.org/docs/app/api-reference/functions/next-request)
*/
export declare class NextRequest extends Request {
[INTERNALS]: {
cookies: RequestCookies;
geo: RequestData['geo'];
ip?: string;
url: string;
nextUrl: NextURL;
};
constructor(input: URL | RequestInfo, init?: RequestInit);
get cookies(): RequestCookies;
get geo(): {
city?: string | undefined;
country?: string | undefined;
region?: string | undefined;
latitude?: string | undefined;
longitude?: string | undefined;
} | undefined;
get ip(): string | undefined;
get nextUrl(): NextURL;
/**
* @deprecated
* `page` has been deprecated in favour of `URLPattern`.
* Read more: https://nextjs.org/docs/messages/middleware-request-page
*/
get page(): void;
/**
* @deprecated
* `ua` has been removed in favour of \`userAgent\` function.
* Read more: https://nextjs.org/docs/messages/middleware-parse-user-agent
*/
get ua(): void;
get url(): string;
}

basePath を "base" に設定して確認する。
next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: '/base',
};
export default nextConfig;
debug 用の Middleware 用意
middleware.ts
import { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
console.debug('Request Url:', request.url);
console.debug(`----------------------------------------`);
console.debug('request.nextUrl.basePath:', request.nextUrl.basePath);
console.debug('request.nextUrl.pathname:', request.nextUrl.pathname);
console.debug('request.nextUrl.href:', request.nextUrl.href);
console.debug('request.nextUrl.toString():', request.nextUrl.toString());
}

"/" にアクセス
Request Url: http://localhost:3000/
----------------------------------------
request.nextUrl.basePath:
request.nextUrl.pathname: /
request.nextUrl.href: http://localhost:3000/
request.nextUrl.toString(): http://localhost:3000/

"/base" にアクセス
Request Url: http://localhost:3000/base
----------------------------------------
request.nextUrl.basePath: /base
request.nextUrl.pathname: /
request.nextUrl.href: http://localhost:3000/base
request.nextUrl.toString(): http://localhost:3000/base

"/base/foo/bar" にアクセス
Request Url: http://localhost:3000/base/foo/bar
----------------------------------------
request.nextUrl.basePath: /base
request.nextUrl.pathname: /foo/bar
request.nextUrl.href: http://localhost:3000/base/foo/bar
request.nextUrl.toString(): http://localhost:3000/base/foo/bar

まとめ
-
nextUrl.basePath
から bathPath の値を参照可能 -
nextUrl.pathame
は、basePath を取り除いた path が入る -
nextUrl.href
は basePath を含んだ実際の request url が入る (request.url と同じ値)

Middleware で redirect する際の url に basePath は自動的に付与されない
NextResponse の redirect や rewrite は引数として受け取った url を redirect/rewrite 先とみなすので、basePath は手動で付与する必要がある。
(一方で、Link や Image など、path を受け取る API は basePath が自動的に prepend されるので考慮する必要はない。)
base
とし、base/proxy
に redirect させたい場合
例) basePath を ❌ basePath を付与しないと /proxy
に redirect されてしまう
middleware.ts
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname !== '/proxy') {
return NextResponse.redirect(new URL('/proxy', request.nextUrl).toString());
}
}
✅ basePath を付与し、/base/proxy
に redirect
middleware.ts
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname !== '/proxy') {
return NextResponse.redirect(
new URL(`${request.nextUrl.basePath}/proxy`, request.nextUrl).toString()
);
}
}

nextUrl の search と searchParams
basePath は影響しない。
nextUrl.search
?
付きの search pararms の string
e.g.) /?query1=value1
の場合
console.log('request.nextUrl.search:', request.nextUrl.search);
request.nextUrl.search: ?query1=value1
nextUrl.searchParams
URLSearchParams が入っている。
e.g.) /?query1=value1
の場合
console.log(
`request.nextUrl.searchParams.get('query1'):`,
request.nextUrl.searchParams.get('query1'),
);
console.log(
'request.nextUrl.searchParams.toString():',
request.nextUrl.searchParams.toString(),
);
/?query1=value1
の場合
request.nextUrl.searchParams.get('query1'): value1
request.nextUrl.searchParams.toString(): query1=value1

next.config.ts の rewrites での basePath
basePath: false or undefined - if false the basePath won't be included when matching, can be used for external rewrites only.
basePath
false は external rewrites でしか使えない。つまり、"basePath を利用している状態で、basePath を含まない path にアクセスした場合に basePath を含めた route に rewrite する" みたいなことはできない。
このスクラップは2024/05/13にクローズされました