Should I use parallel routes?
Answered
Rhinelander posted this in #help-forum
RhinelanderOP
Layout.tsx
Is this approach recommended? 75% stuff will be different between roles (different views)
import { SidebarProvider } from "@/components/ui/sidebar";
import { auth } from "@/modules/auth/lib/auth";
import { DashboardNavbar } from "@/modules/dashboard/components/common/dashboard-navbar";
import { DashboardSidebar } from "@/modules/dashboard/components/common/dashboard-sidebar";
import { headers } from "next/headers";
type DashboardLayoutProps = {
user: React.ReactNode;
admin: React.ReactNode;
partner: React.ReactNode;
};
export default async function DashboardLayout(props: DashboardLayoutProps) {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session || !session.user.role) {
return null;
}
const { role } = session.user;
return (
<SidebarProvider>
<DashboardSidebar />
<main className="flex-1">
<DashboardNavbar />
{props[role as keyof typeof props]}
</main>
</SidebarProvider>
);
}
Is this approach recommended? 75% stuff will be different between roles (different views)
Answered by joulev
so what happens when you go to a route is that, all page.tsx files corresponding to that route are all evaluated.
nextjs doesn't have a compilation system that can analyse the code and figure out it can get away with not rendering the
@admin/.../page.tsx
, @partner/.../page.tsx
and @user/.../page.tsx
are all ran and the outputs are put in the admin
, partner
and user
slots respectively. you simply choose not to use two of the three slots, but those unused slots are still evaluated. that's the biggest problem with the parallel route approach.nextjs doesn't have a compilation system that can analyse the code and figure out it can get away with not rendering the
@admin/.../page.tsx
file at all when a partner user is visiting.10 Replies
@Rhinelander **Layout.tsx**
ts
import { SidebarProvider } from "@/components/ui/sidebar";
import { auth } from "@/modules/auth/lib/auth";
import { DashboardNavbar } from "@/modules/dashboard/components/common/dashboard-navbar";
import { DashboardSidebar } from "@/modules/dashboard/components/common/dashboard-sidebar";
import { headers } from "next/headers";
type DashboardLayoutProps = {
user: React.ReactNode;
admin: React.ReactNode;
partner: React.ReactNode;
};
export default async function DashboardLayout(props: DashboardLayoutProps) {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session || !session.user.role) {
return null;
}
const { role } = session.user;
return (
<SidebarProvider>
<DashboardSidebar />
<main className="flex-1">
<DashboardNavbar />
{props[role as keyof typeof props]}
</main>
</SidebarProvider>
);
}
Is this approach recommended? 75% stuff will be different between roles (different views)
no... because say you are a normal user accessing the route, the server will still have to render the admin and partner routes despite not displaying them
instead just use conditionals.
instead just use conditionals.
if (user.role === "admin") return <AdminView />;
RhinelanderOP
Why do they mention that in the docs? https://nextjs.org/docs/app/building-your-application/routing/parallel-routes#examples
"You can use Parallel Routes to conditionally render routes based on certain conditions, such as user role"
your
then in the parallel route system, line A will always be executed regardless of what role the user is. only line B is skipped if the role is not
so if you ensure the line A part of your application is always fast, it should be fine. but if the line A part of your application is slow for
so yeah there is nuance to this and whether it's good or not depends a lot on how you write your routes. that's why this is not how i prefer to handle it. my preferences:
1. clear route structure e.g. admin user pages are always at
2. OR rewriting. e.g. rewriting
3. OR conditional rendering:
page.tsx
probably looks like thisexport default async function AdminPage() {
const user = await auth();
// line A
if (user.role !== "admin") return null;
// line B
...
}
then in the parallel route system, line A will always be executed regardless of what role the user is. only line B is skipped if the role is not
"admin"
.so if you ensure the line A part of your application is always fast, it should be fine. but if the line A part of your application is slow for
"partner"
, everyone will have to wait for that section and not just the partner users.so yeah there is nuance to this and whether it's good or not depends a lot on how you write your routes. that's why this is not how i prefer to handle it. my preferences:
1. clear route structure e.g. admin user pages are always at
/admin/*
instead of sharing the same path with ordinary users2. OR rewriting. e.g. rewriting
/
to /home
for public users and to /dashboard
for authenticated users, like how vercel.com and github.com are doing3. OR conditional rendering:
if (user.role === "admin") return <AdminStuff />
. make it explicit and you don't risk making ordinary users wait for admin user requests.RhinelanderOP
I prefer stuff that you just mentioned. It is very good approach, but I really like the way I can simply write routes without this routes starting with /:user-role/*. So I redirect users in if ther are authenticated - but I don't check roles. Roles I check in
(dashboard)/layout.tsx
- code above. I don't want to sacrifice performance but from the docs I couldn't clarify if @admin @partner @users are all rendered despite the role.@Rhinelander I prefer stuff that you just mentioned. It is very good approach, but I really like the way I can simply write routes without this routes starting with /:user-role/*. So I redirect users in if ther are authenticated - but I don't check roles. Roles I check in (dashboard)/layout.tsx - code above. I don't want to sacrifice performance but from the docs I couldn't clarify if @admin @partner @users are all rendered despite the role.
so what happens when you go to a route is that, all page.tsx files corresponding to that route are all evaluated.
nextjs doesn't have a compilation system that can analyse the code and figure out it can get away with not rendering the
@admin/.../page.tsx
, @partner/.../page.tsx
and @user/.../page.tsx
are all ran and the outputs are put in the admin
, partner
and user
slots respectively. you simply choose not to use two of the three slots, but those unused slots are still evaluated. that's the biggest problem with the parallel route approach.nextjs doesn't have a compilation system that can analyse the code and figure out it can get away with not rendering the
@admin/.../page.tsx
file at all when a partner user is visiting.Answer
RhinelanderOP
Aha now I understand. I wonder how much "evaluation costs in my example" - is there a way to test that?
@Rhinelander Aha now I understand. I wonder how much "evaluation costs in my example" - is there a way to test that?
it would be the time and resource required to run the
Page
function until the return statement – the line A in my example above. if your code immediately returns, the impact is negligible, but if your code runs expensive code before you return anything, that will be a wasted resourceRhinelanderOP
Thank you very much!