How to dynamically import components either locally or remotely?
Unanswered
American Crocodile posted this in #help-forum
American CrocodileOP
In a Next.js v13.4 app using the pages router, TypeScript and Material UI. I got this folder structure
The project Idea is to load a template based on the URL subdomain.
This is how the
- The
- The
- The
I need to find a way to separate the
root/
pages/
public/
src/
features/
shared/
templates/
template_one/
assets/
components/
contents/
locales/
theme/
template_two/
assets/
components/
contents/
locales/
theme/
template_three/
assets/
components/
contents/
locales/
theme/
template_four/
assets/
components/
contents/
locales/
theme/The project Idea is to load a template based on the URL subdomain.
This is how the
src directory structured:- The
features directory contains all the logic used across the app.- The
shared directory contains a combination of components, constants, enums, hook, etc.. that are being used across the app.- The
templates directory contains all the templates each one in it's directory and each one has it's own components, contents (pages eg. Home, AboutUs, ContactUs, etc..), locales (JSON files for translations), theme (a .ts file contains Material UI theme configurations).I need to find a way to separate the
templates directory from the app either locally or remotely, so the app is only responsible for deciding which template to render.1 Reply
American CrocodileOP
This is how I'm handling templates rendering so far
import { Pages } from '@/features/pages/enums';
import { Page, PageTitle } from '@/features/pages/types';
import ErrorBoundary from '@/shared/components/ErrorBoundary';
import { Routes } from '@/shared/enums/routes';
import { AppThemeData } from '@/shared/types/appTheme';
import { camelCaseSlug } from '@/shared/utilities/text';
import Box from '@mui/material/Box';
import { ThemeProvider } from '@mui/material/styles';
import dynamic from 'next/dynamic';
import { memo } from 'react';
import ErrorView from '../ErrorView';
import LoadingView from '../LoadingView';
type Props = {
themeName: string;
themeData: AppThemeData;
slug: string;
id?: string;
page?: null | Page;
};
export type ContentProps = {
slug?: string;
id?: string;
};
const Snackbar = dynamic(() => import('@/shared/components/Snackbar'));
const PageContent = ({ page, themeName, themeData, slug, id }: Props) => {
const key = slug === Routes.ROOT ? 'Home' : camelCaseSlug(slug);
const Header = dynamic(() => import(`@/templates/${themeName}/components/Header`).catch((error) => ({ default: () => null })));
const Content = dynamic<ContentProps>(() => import(`@/templates/${themeName}/contents/${key}`).catch((error) => ({ default: () => <ErrorView /> })), { loading: () => <LoadingView /> });
const Footer = dynamic(() => import(`@/templates/${themeName}/components/Footer`).catch((error) => ({ default: () => null })));
return (
<ThemeProvider theme={themeData}>
<ErrorBoundary>
<Header />
<Box component={'main'} display={'flex'} flexDirection={'column'} flex={1}>
<Content slug={slug} id={id} />
</Box>
<Footer />
<Snackbar />
</ErrorBoundary>
</ThemeProvider>
);
};
export default memo(PageContent);