import { Suspense } from "react"; import dynamic from "next/dynamic"; import { getDictionary } from "@/lib/dictionaries"; import { Hero } from "@/components/sections/Hero"; import { Features } from "@/components/sections/Features"; const SectionSkeleton = () => (
); // Тяжёлые интерактивные секции (framer-motion анимации, клиентские запросы к PocketBase, // realtime-подписки) грузятся через next/dynamic, а не обычным import, чтобы не раздувать // первый JS-бандл главной страницы: Hero и Features рендерятся сразу (статично, легче), // а Pricing/FAQ/TerminalGuestbook/BlogPreview подгружаются отдельными чанками с плейсхолдером // SectionSkeleton, пока грузится JS. const Pricing = dynamic( () => import("@/components/sections/Pricing").then((mod) => mod.Pricing), { loading: () => }, ); const FAQ = dynamic( () => import("@/components/sections/Faq").then((mod) => mod.FAQ), { loading: () => }, ); const TerminalGuestbook = dynamic( () => import("@/components/sections/TerminalGuestbook").then( (mod) => mod.TerminalGuestbook, ), { loading: () => }, ); const BlogPreview = dynamic(() => import("@/components/sections/BlogPreview").then((mod) => mod.BlogPreview), ); export default async function Home({ params, }: { params: Promise<{ lang: string }>; }) { const { lang } = await params; const dict = await getDictionary(lang); // Читаем PB_PUBLIC_URL, а не NEXT_PUBLIC_PB_URL: Next.js статически подставляет // NEXT_PUBLIC_*-переменные везде, где они встречаются в коде (в т.ч. внутри серверных // компонентов), на этапе `next build` — так что чтение NEXT_PUBLIC_PB_URL здесь давало бы // то же самое собранное-в-образ значение, что и в клиентском бандле. PB_PUBLIC_URL — // обычная (не NEXT_PUBLIC_) переменная, поэтому читается по-настоящему заново при каждом // запросе (см. подробный комментарий в app/[lang]/auth/auth-client.tsx про ACCOUNT_ORIGIN). const pbUrl = process.env.PB_PUBLIC_URL || "https://netrunner-vpn.com/cms-api"; return ( <> }> ); }