Reputation: 83
I have a Next.js application where I'm dynamically loading portfolio templates based on user preferences. While the functionality works, I noticed in the developer console that all template files are being fetched, even though only one template is needed at a time.
I have a dynamic route [username]
that loads user data and their chosen template:
// app/[username]/page.tsx
import { notFound } from "next/navigation";
import data from "@/public/FakeData.json"
const users = data.users;
export default async function userPortfolio({ params }: { params: { username: string } }) {
const user = users.filter((u)=>{
return u.username == params.username;
}).at(0);
if (!user) {
return notFound();
}
let userTemplate = user.template;
// This loads all template files even though we only need one
const TemplatePage = (await import(`@/components/Templates/${userTemplate}/${userTemplate}_Portfolio`)).default;
return (
<TemplatePage userDetails={user} />
);
}
My template files are structured like this:
components/
Templates/
Marc/
Marc_Portfolio.jsx
Rahul/
Rahul_Portfolio.tsx
When a user visits /james123
and their template is "Marc", only the Marc template files should be fetched, not the Rahul template files.
When checking the Network tab in Chrome DevTools, I can see that files from all templates are being fetched, even though only one template is being used.
How can I optimize the dynamic imports to only fetch the specific template files that are needed, without loading other template files?
template
property that specifies which template to useI've attempted using dynamic imports with template strings, but this seems to cause Next.js to include all possible template files in the bundle.
Upvotes: 0
Views: 35
Reputation: 83
Here’s a refined version of your solution with improved grammar, explanation, and structure for better clarity:
To solve this issue, I used next/dynamic
to dynamically import the required template. However, I initially encountered an error:
'ssr: false' is not allowed with `next/dynamic` in Server Components. Please move it into a client component.
Since ssr: false
requires a Client Component, I created a separate client-side component to handle the dynamic import.
I created a schema file (types.ts
) to define the types for user data and component props:
export interface UserSchema {
username: string;
template: string;
name: string;
profile_picture: string;
location: string;
cvURL: string;
contact: {
email: string;
linkedin: string;
github: string;
};
profile_summary: string;
experience: any[];
}
export interface TemplatePageProps {
userDetails: UserSchema;
}
export interface ClientTemplateProps {
user: UserSchema;
templateName: string;
}
I created a separate client component (ClientTemplate.tsx
) to dynamically load the required template based on the user's templateName
.
'use client';
import dynamic from 'next/dynamic';
import { ClientTemplateProps, TemplatePageProps } from './types';
export default function ClientTemplate({ user, templateName }: ClientTemplateProps) {
const TemplatePage = dynamic<TemplatePageProps>(
() => import(`@/components/Templates/${templateName}/${templateName}_Portfolio`),
{ ssr: false }
);
return <TemplatePage userDetails={user} />;
}
ssr: false
option ensures that the template is loaded dynamically in the browser rather than preloaded on the server.page.tsx
to Use the Client ComponentFinally, I updated page.tsx
to use ClientTemplate
for rendering the correct template dynamically:
import { notFound } from "next/navigation";
import ClientTemplate from "./ClientTemplate";
import data from "@/public/FakeData.json";
const users = data.users;
export default async function userPortfolio({ params }: { params: { username: string } }) {
const user = users.find((u) => u.username === params.username);
if (!user) return notFound();
return <ClientTemplate user={user} templateName={user.template} />;
}
Upvotes: 0