NoSsr для отключения SSR

В библиотеке MUI (Material-UI) компонент NoSsr предназначен для контроля рендеринга на стороне клиента, позволяя временно отключить Server-Side Rendering (SSR) для определённых компонентов или их частей. Это особенно актуально для компонентов, которые зависят от браузерного окружения, например, использующих window, document или специфические сторонние библиотеки.


Основная концепция NoSsr

Компонент NoSsr оборачивает любой дочерний элемент и гарантирует, что этот элемент не будет рендериться на сервере. В момент серверного рендеринга он не создаёт разметку, предотвращая ошибки, связанные с отсутствием браузерного API. После монтирования на клиенте компонент отобразится автоматически.

import * as React from 'react';
import NoSsr from '@mui/base/NoSsr';
import SomeBrowserComponent from './SomeBrowserComponent';

function Example() {
  return (
    <NoSsr>
      <SomeBrowserComponent />
    </NoSsr>
  );
}

В этом примере SomeBrowserComponent не будет рендериться на сервере, что предотвращает ошибки при обращении к window или document.


Свойства компонента NoSsr

NoSsr поддерживает несколько ключевых свойств, позволяющих тонко управлять поведением:

  1. children Любой React-элемент или группа элементов, которые должны быть отрендерены только на клиенте.

  2. fallback Элемент, который будет отображаться на сервере вместо children. Может быть полезен для показа загрузочного индикатора или заглушки:

<NoSsr fallback={<div>Загрузка...</div>}>
  <SomeBrowserComponent />
</NoSsr>
  1. defer Булевое значение. Если установлено в true, children будут рендериться на клиенте после первого эффекта (useEffect). Это полезно для уменьшения времени до первого рендеринга страницы:
<NoSsr defer>
  <SomeBrowserComponent />
</NoSsr>

Свойство defer особенно важно при SSR, так как оно предотвращает мерцание контента и ускоряет первый визуальный рендер.


Практическое применение

Отключение SSR для интерактивных компонентов

Многие интерактивные элементы, такие как графики, карты или компоненты с анимацией, требуют работы браузерного окружения. Использование NoSsr позволяет безопасно интегрировать такие компоненты в серверный рендеринг:

import Chart from 'react-chartjs-2';

function ChartWrapper() {
  return (
    <NoSsr fallback={<p>График загружается...</p>}>
      <Chart data={chartData} />
    </NoSsr>
  );
}

Совместное использование с динамическим импортом

NoSsr хорошо сочетается с React lazy и Suspense для динамического импорта:

import React, { lazy, Suspense } from 'react';
import NoSsr from '@mui/base/NoSsr';

const LazyComponent = lazy(() => import('./LazyComponent'));

function DynamicExample() {
  return (
    <NoSsr fallback={<p>Загрузка компонента...</p>}>
      <Suspense fallback={<p>Идёт загрузка...</p>}>
        <LazyComponent />
      </Suspense>
    </NoSsr>
  );
}

Такой подход позволяет полностью избежать ошибок при рендеринге на сервере и управлять загрузкой компонентов.


Важные нюансы использования

  • NoSsr не предназначен для скрытия контента от пользователя, он лишь управляет местом рендеринга — сервер или клиент.
  • При использовании defer контент может отображаться с задержкой после монтирования. Это может привести к layout shift, если не предусмотрены placeholder или fallback.
  • Компонент можно вкладывать друг в друга для разных уровней контроля рендеринга.
<NoSsr>
  <SomeClientOnlyWrapper>
    <NoSsr defer>
      <InteractiveWidget />
    </NoSsr>
  </SomeClientOnlyWrapper>
</NoSsr>

Резюме ключевых моментов

  • NoSsr позволяет исключить рендеринг на сервере для компонентов, зависящих от браузера.
  • Использование свойства fallback обеспечивает корректное отображение заглушки на сервере.
  • defer даёт возможность отложенного рендеринга на клиенте после эффекта, минимизируя возможные конфликты при SSR.
  • Совместимость с lazy и Suspense позволяет создавать динамически загружаемые, безопасные для SSR компоненты.

Эффективное применение NoSsr повышает стабильность SSR-проектов и предотвращает ошибки, связанные с клиентскими зависимостями, сохраняя при этом плавный и безопасный рендеринг на сервере и клиенте.