So basically I have a server component in app dir and I want to get the pathname. I tried to do it using window.location but it does not work. Is there any way I can do this?
-
I don't think window exists on the serverside. Consider using the path module and dirname?evolutionxbox– evolutionxbox2023-02-06 14:30:59 +00:00Commented Feb 6, 2023 at 14:30
-
I already know that window does not exists, but thanks anywaysUpdater XD– Updater XD2023-02-06 14:38:20 +00:00Commented Feb 6, 2023 at 14:38
-
1found some info on answer by @and-yet-it-compiles in documentation "Using cookies() or headers() in a Server Component will opt the whole route into dynamic rendering at request time." source: nextjs.org/docs/app/building-your-application/rendering/…artifii– artifii2023-05-31 08:07:15 +00:00Commented May 31, 2023 at 8:07
-
just add {params} to the server function and you will get the pathname.PugProvoleta– PugProvoleta2023-12-28 13:34:29 +00:00Commented Dec 28, 2023 at 13:34
-
nextjs15 server component: const symbols = Object.getOwnPropertySymbols(globalThis); const needed = symbols[symbols.length - 1]; // @ts-ignore console.log(Object.keys(globalThis[needed].clientReferenceManifestsPerPage)[0]);Frost Draky– Frost Draky2025-03-03 14:25:03 +00:00Commented Mar 3 at 14:25
7 Answers
Take a look at https://github.com/vercel/next.js/issues/43704 , pauliusuza solved this issue
You can do a workaround using a middleware
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
// Store current request url in a custom header, which you can read later
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-url', request.url);
return NextResponse.next({
request: {
// Apply new request headers
headers: requestHeaders,
}
});
}
Then use it from inside of a root layout:
import { headers } from 'next/headers';
export default function RootLayout() {
const headersList = headers();
// read the custom x-url header
const header_url = headersList.get('x-url') || "";
}
Hope that helps
7 Comments
x-invoke-path headerhttp://localhost:3000/fa it works. But if then we navigate to /en page (e.g. by clicking on <Link href='/en' ...) the middleware works, but the layout component doesn't rerender!Alternatively, I think an even easier solution would be to use Next's headers already present in the request, like host or refer.
Example:
import { headers } from 'next/headers';
export default function Navbar() {
const headersList = headers();
const domain = headersList.get('host') || "";
const fullUrl = headersList.get('referer') || "";
console.log(fullUrl);
}
2 Comments
referer is the URL that you came from, not the URL of the page you're on.new URL(fullurl).pathname :)NextJS v14 Serverside get Pathname
import { headers } from "next/headers";
const heads = headers()
const pathname = heads.get('next-url')
Heads-up: it might have performance implications. From the NextJS documentation:
Good to know:
headers() is a Dynamic Function whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into dynamic rendering at request time.
Important! The VP of Product @vercel discourages the use of the next-url header
8 Comments
next-url header sometimes, it is not working reliably. Not in dev mode and not in production on vercel.This works for me
import { headers } from "next/headers";
const headersList = headers();
const domain = headersList.get("x-forwarded-host") || "";
const protocol = headersList.get("x-forwarded-proto") || "";
const pathname = headersList.get("x-invoke-path") || "";
4 Comments
create a middleware.ts in the src dir of your app, it would be responsible for urls of your application, i added some other useful properties such as origin which is good for calling internal api and the pathname for accessing the path of your component; note that it only can be used inside server component
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
const url = new URL(request.url);
const origin = url.origin;
const pathname = url.pathname;
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-url', request.url);
requestHeaders.set('x-origin', origin);
requestHeaders.set('x-pathname', pathname);
return NextResponse.next({
request: {
headers: requestHeaders,
}
});
}
and in your server components use it like
import { headers } from "next/headers";
export default async function page() {
const headersList = headers()
const header_url = headersList.get('x-url') || "";
const pathname = headersList.get('x-pathname');
const origin_url = headersList.get('x-origin');
}
Comments
This finds the pathname assuming you got a referer cookie:
import { headers } from 'next/headers';
const domain = headersList.get('host') || "";
const fullUrl = headersList.get('referer') || "";
const [,pathname] = fullUrl.match( new RegExp(`https?:\/\/${domain}(.*)`))||[];
console.log(pathname);
3 Comments
This answer is almost correct . Using app directory with src pattern I realized that I need to change the middleware.ts placement like the following.
.
├── src
│ ├── app
│ └── middleware.ts