fullPage.js — это библиотека для создания полноэкранных скролл-сайтов с плавной навигацией между секциями и слайдерами. Обычно её используют в браузере, управляя DOM напрямую, но при серверном рендеринге (SSR) возникают особенности, которые важно учитывать.
При серверном рендеринге важно понимать, что на сервере нет
окна (window) и документа (document).
fullPage.js активно взаимодействует с DOM, создавая обёртки для секций,
добавляя навигационные элементы и прослушивая события скролла. Это
значит, что инициализация fullPage.js на сервере напрямую вызовет ошибки
типа ReferenceError: window is not defined.
Для обхода этой проблемы применяют условную инициализацию:
if (typeof window !== 'undefined') {
import('fullpage.js').then(({ default: fullpage }) => {
new fullpage('#fullpage', {
autoScrolling: true,
navigation: true,
anchors: ['firstPage', 'secondPage', 'thirdPage'],
});
});
}
Здесь проверка typeof window !== 'undefined'
гарантирует, что код fullPage.js выполнится только в браузере.
В Next.js компоненты можно разделять на динамические и
обычные. fullPage.js удобно подключать через динамический
импорт с опцией ssr: false:
import dynamic from 'next/dynamic';
const FullpageWrapper = dynamic(() => import('../components/FullpageComponent'), {
ssr: false
});
export default function Home() {
return <FullpageWrapper />;
}
Внутри FullpageComponent используется стандартная
инициализация fullPage.js через useEffect:
import { useEffect } from 'react';
import fullpage from 'fullpage.js';
export default function FullpageComponent() {
useEffect(() => {
new fullpage('#fullpage', {
autoScrolling: true,
navigation: true
});
return () => fullpage.destroy('all');
}, []);
return (
<div id="fullpage">
<div className="section">Section 1</div>
<div className="section">Section 2</div>
<div className="section">Section 3</div>
</div>
);
}
useEffect выполняется только на клиенте, поэтому
серверный рендеринг не вызывает ошибок.
Для Vue-проектов с SSR библиотеку подключают через
onMounted или динамический импорт:
<template>
<div id="fullpage">
<section class="section">Section 1</section>
<section class="section">Section 2</section>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(async () => {
const fullpage = (await import('fullpage.js')).default;
new fullpage('#fullpage', {
autoScrolling: true,
navigation: true
});
});
</script>
onMounted гарантирует, что DOM полностью создан на
клиенте до инициализации fullPage.js.
Минимизация блокирующего JS fullPage.js тяжеловесен, поэтому желательно загружать его асинхронно и только для страниц с полноэкранным скроллом. Для остальных страниц можно использовать статическую разметку без инициализации.
Разделение секций на компоненты Каждую секцию удобно выносить в отдельный компонент. Это позволяет серверу рендерить базовую структуру страниц с контентом, а fullPage.js управляет только навигацией и анимациями на клиенте.
Отложенная инициализация Иногда полезно
инициализировать fullPage.js после полной загрузки изображений или
данных через window.addEventListener('load', ...). Это
снижает вероятность дерганий и визуальных артефактов.
fullPage.js позволяет привязывать секции к anchor-строкам. При SSR важно генерировать разметку секций с правильными id, чтобы при первичном рендере на сервере ссылки уже работали. Например:
<div id="fullpage">
<div class="section" data-anchor="home">Home</div>
<div class="section" data-anchor="about">About</div>
</div>
Это позволяет SEO-ботам индексировать страницы и сохраняет корректность URL при клиентской навигации.
При SSR данные часто загружаются заранее. Для fullPage.js важно,
чтобы контент секций был уже на странице при инициализации. Если данные
подгружаются асинхронно после mount, необходимо обновить
fullPage.js, например, с помощью методов
fullpage.reBuild():
// После добавления или удаления секций
fullpage_api.reBuild();
ES modules).Полноэкранный скролл с fullPage.js при серверном рендеринге требует
продуманного разделения клиентского и серверного кода, корректной
генерации секций и безопасной инициализации через динамический импорт
или хуки useEffect / onMounted. Это
обеспечивает совместимость с SSR-фреймворками и улучшает
производительность и SEO.