Optimize mobile load by lazy loading large modules
All checks were successful
Build & Push Docker Image / docker (push) Successful in 1m48s

This commit is contained in:
Ahmed Darrazi 2025-12-18 15:23:00 +01:00
parent af68304404
commit c00f58bced
5 changed files with 52 additions and 37 deletions

View File

@ -1,5 +1,6 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { SidebarMenuButton, useSidebar } from '@/components/ui/sidebar';
import { useIsMobile } from '@/hooks/use-mobile';
import { routeLastSegment, routeSecondSegment } from '@/lib/route';
import { cn } from '@/lib/utils';
import { SharedData } from '@/types/global';
@ -14,6 +15,7 @@ const NavMainItem = (props: NavMainItemProps) => {
const page = usePage<SharedData>();
const { auth, direction } = page.props;
const { state, toggleSidebar } = useSidebar();
const isMobile = useIsMobile();
const { pageRoute } = props;
const { Icon, name, path, children, slug } = pageRoute;
@ -67,7 +69,7 @@ const NavMainItem = (props: NavMainItemProps) => {
if (access.includes(auth.user.role)) {
return (
<SidebarMenuButton asChild key={index} isActive={activeChildRoute(pageRoute.slug, slug)} className="h-9 px-3">
<Link href={path} prefetch>
<Link href={path} prefetch={!isMobile}>
<Dot className="w-12" />
<span className="text-sm font-normal capitalize">{name}</span>
</Link>
@ -88,7 +90,7 @@ const NavMainItem = (props: NavMainItemProps) => {
: '',
)}
>
<Link href={path} prefetch>
<Link href={path} prefetch={!isMobile}>
<Icon className="h-4 w-4" />
<span>{name}</span>
</Link>

View File

@ -1,5 +1,6 @@
import AppLogo from '@/components/app-logo';
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuItem, useSidebar } from '@/components/ui/sidebar';
import { useIsMobile } from '@/hooks/use-mobile';
import { NavMain } from '@/layouts/dashboard/partials/nav-main';
import { NavUser } from '@/layouts/dashboard/partials/nav-user';
import { SharedData } from '@/types/global';
@ -9,6 +10,7 @@ const DashboardSidebar = () => {
const { state } = useSidebar();
const { props } = usePage<SharedData>();
const compact = state === 'collapsed' ? true : false;
const isMobile = useIsMobile();
return (
<Sidebar collapsible="icon" variant="inset" side={props.direction === 'rtl' ? 'right' : 'left'} className="shadow-md">
@ -16,7 +18,7 @@ const DashboardSidebar = () => {
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem className="pt-1 pb-5">
<Link href="/" prefetch>
<Link href="/" prefetch={!isMobile}>
<AppLogo className="h-[26px]" />
</Link>
</SidebarMenuItem>

View File

@ -3,14 +3,16 @@ import RatingStars from '@/components/rating-stars';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
import VideoPlayer from '@/components/video-player';
import { getPageSection, getPropertyArray } from '@/lib/page';
import { cn } from '@/lib/utils';
import { IntroPageProps } from '@/types/page';
import { Link, usePage } from '@inertiajs/react';
import { Play } from 'lucide-react';
import { lazy, Suspense } from 'react';
import Section from '../section';
const VideoPlayer = lazy(() => import('@/components/video-player'));
const Hero = () => {
const { props } = usePage<IntroPageProps>();
const { page } = props;
@ -65,6 +67,7 @@ const Hero = () => {
</DialogTrigger>
<DialogContent className="overflow-hidden p-0 md:min-w-3xl">
<Suspense fallback={null}>
<VideoPlayer
source={{
type: 'video' as const,
@ -76,6 +79,7 @@ const Hero = () => {
],
}}
/>
</Suspense>
</DialogContent>
</Dialog>
)}

View File

@ -1,12 +1,14 @@
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
import VideoPlayer from '@/components/video-player';
import { getPageSection } from '@/lib/page';
import { IntroPageProps } from '@/types/page';
import { usePage } from '@inertiajs/react';
import { File, FileQuestion, FileText, Image, Play, Video } from 'lucide-react';
import { lazy, Suspense } from 'react';
import Section from '../section';
const VideoPlayer = lazy(() => import('@/components/video-player'));
const TopCourse = () => {
const { props } = usePage<IntroPageProps>();
const { page, topCourse, customize } = props;
@ -34,6 +36,7 @@ const TopCourse = () => {
</DialogTrigger>
<DialogContent className="overflow-hidden p-0 md:min-w-3xl">
<Suspense fallback={null}>
<VideoPlayer
source={{
type: 'video' as const,
@ -45,6 +48,7 @@ const TopCourse = () => {
],
}}
/>
</Suspense>
</DialogContent>
</Dialog>
)}

View File

@ -1,8 +1,9 @@
import SectionEditor from '@/components/section-editor';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { Pencil } from 'lucide-react';
import { ReactNode } from 'react';
import { lazy, ReactNode, Suspense } from 'react';
const SectionEditor = lazy(() => import('@/components/section-editor'));
interface SectionProps extends React.HTMLAttributes<HTMLDivElement> {
children: ReactNode;
@ -19,6 +20,7 @@ const Section = ({ containerClass, contentClass, children, pageSection, customiz
<section className={cn('container', containerClass)} {...props} style={containerStyle}>
<div className={cn(contentClass, customize && 'section-edit')} style={contentStyle}>
{customize && pageSection && (
<Suspense fallback={null}>
<SectionEditor
section={pageSection}
actionComponent={
@ -27,6 +29,7 @@ const Section = ({ containerClass, contentClass, children, pageSection, customiz
</Button>
}
/>
</Suspense>
)}
{/* Content */}