Closed10

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

nbstshnbstsh
nbstshnbstsh

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;
}
nbstshnbstsh

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());
}
nbstshnbstsh

"/" にアクセス

Request Url: http://localhost:3000/
----------------------------------------
request.nextUrl.basePath: 
request.nextUrl.pathname: /
request.nextUrl.href: http://localhost:3000/
request.nextUrl.toString(): http://localhost:3000/
nbstshnbstsh

"/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
nbstshnbstsh

"/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
nbstshnbstsh

まとめ

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

Middleware で redirect する際の url に basePath は自動的に付与されない

NextResponse の redirect や rewrite は引数として受け取った url を redirect/rewrite 先とみなすので、basePath は手動で付与する必要がある。

(一方で、Link や Image など、path を受け取る API は basePath が自動的に prepend されるので考慮する必要はない。)

例) basePath を base とし、base/proxy に redirect させたい場合

❌ 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()
    );
  }
}
nbstshnbstsh

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
nbstshnbstsh

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 する" みたいなことはできない。

https://nextjs.org/docs/pages/api-reference/config/next-config-js/rewrites

このスクラップは2024/05/13にクローズされました