1

I have a Next.js Server Side Rendered app where I need to load components dynamically.

e.g Homepage, I make an API call in getServerSideProps to fetch homepage data, which will consist of some basic information about the page along with names of all the components and data for each component. From here I need to render these components dynamically in the page body. And these dynamic components need to be rendred on the server for SEO.

Here is my simplified code

import Head from 'next/head';
import Header from '../components/Header';
import Banner from '../components/Banner';

import { getDomainFromContext, getParamFromContext } from '../src/utils';
import { fetchPage } from '../src/fetchers';

export async function getServerSideProps(context) {
    const domain = getDomainFromContext(context);
    const locale = getParamFromContext(context, 'locale');
    const uri = '/';

    const page = await fetchPage(domain, uri, locale);

    /*
        page now has names of the components with data for each component. e.g
        {
            ...
            components : {
                {
                    "name" : "Venues",
                    "data" : "..."
                },
                {
                    "name" : "Info",
                    "data" : "..."
                }
            }
            ...
        }
     */


    return {
        props: {
            domain: domain,
            locale: locale,
            page: page
        },
    };
}

function Home(props) {
    
    return (
        <>
            <Head>
                <title>Create Next App</title>
                <meta name="description" content="Generated by create next app" />
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <Header>
                <h1>Homepage</h1>
            </Header>

            <main>
                <Banner />
                {/*Load Dynamic components here & it should be server side rendered.*/}
            </main>
        </>
    );
}

export default Home;
Sohail
  • 2,058
  • 7
  • 33
  • 57
  • https://nextjs.org/docs/advanced-features/dynamic-import...I guess you are talking about this – kazmi066 Jul 21 '22 at 14:20
  • Thanks @kazmi066. I think this will work. I overlooked that at first thinking its only for lazy loading components on the client. But I think it works for SSR too. Will post a full code snippet with the solution using dynamic import soon. – Sohail Jul 22 '22 at 07:42

1 Answers1

0

So I based my solution on the answer in this question : Dynamic Importing of an unknown component - NextJs

I created a function that accepts component name to load, and once I have the component names from the API, I loop through component names to load & save them in an array, and save data in an array as well. Later components are rendered from the array.

import Head from 'next/head';
import Header from '../components/Header';
import { getDomainFromContext, getParamFromContext } from '../src/utils';
import { fetchPage } from '../src/fetchers';
import { Suspense } from 'react';


export function getDynamicComponent(c) {
    return dynamic(() => import(`../components/${c}`), {
        suspense: true,
    });
}

export async function getServerSideProps(context) {
    let domain = getDomainFromContext(context);
    let locale = getParamFromContext(context, 'locale');
    let pageUri = '/'


    const page = await fetchPage(companyId, pageUri);

    return {
        props: {
            domain: domain,
            locale: locale,
            page: page,
        },
    };
}

function Home(props) {
    
    let components = [];
    let componentsData = [];

    props.page.components.forEach((component, i) => {
        components.push(getDynamicComponent(component.name));
        componentsData.push(component.data);
    });

    return (
        <>
            <Head>
                <title>Create Next App</title>
                <meta name="description" content="Generated by create next app" />
                <link rel="icon" href="/favicon.ico" />
            </Head>

            <Header>
                <h1>Homepage</h1>
            </Header>

            <main>
                <Suspense fallback={`...`}>
                    {components.map((Component, k) => (
                        <Component key={k} data={componentsData.data[k]} />
                    ))}
                </Suspense>
            </main>
        </>
    );
}

export default Home;
Sohail
  • 2,058
  • 7
  • 33
  • 57