JavaRush /Курсы /Модуль 3: React /Обсуждение сложных случаев и вопросов по SSR

Обсуждение сложных случаев и вопросов по SSR

Модуль 3: React
13 уровень , 9 лекция
Открыта

Что делает SSR сложным?

SSR — это не только способ улучшить SEO и ускорить загрузку страниц, но и процесс, который может вызвать головную боль при неправильной настройке. Представьте, что вы пытаетесь приготовить лазанью, но без рецепта: ингредиенты есть, но в какой-то момент тесто пересыхает, а сыр подгорает. Так и с SSR: не всё здесь гладко, если не знать определённых тонкостей. Вот несколько аспектов, которые часто вызывают трудности:

  • Интеграция с внешними API: что делать, если API медленный или недоступен?
  • Глобальное состояние: как передать данные между серверным и клиентским рендерингом?
  • Динамические маршруты и SEO: как обработать сложные URL и поисковые запросы с параметрами?
  • Асинхронные запросы: как обрабатывать их с учётом ограничений производительности сервера?

Если SSR — это ваш супергерой, который спасает ваш сайт от медленной загрузки и плохого SEO, то реальная жизнь — это Лекс Лютор с миллионом ловушек. Но не волнуйтесь, мы всё разберём!

Сложные кейсы использования SSR

Сценарий 1: медленный API

Представьте, что вы делаете запрос к внешнему API для получения данных, а он отвечает с задержкой в 3-5 секунд. Это автоматически увеличивает время загрузки страницы.

Решение:

  1. Используйте кэширование. Например, данные, которые редко меняются, можно кэшировать либо на уровне API, либо на уровне вашего сервера.
  2. Или объедините SSR с определённым уровнем Static Site Generation (SSG). Next.js позволяет использовать getStaticProps для генерации страниц в момент билда. Это может быть полезно для страниц, которые не требуют динамического контента.
export const getServerSideProps = async () => {
  const cachedData = getCachedData(); // Ищем данные в кэше
  if (cachedData) {
    return { props: { data: cachedData } };
  }

  // Получаем данные с API
  const response = await fetch("https://example.com/api");
  const data = await response.json();

  // Кэшируем данные для будущих запросов
  saveToCache(data);

  return { props: { data } };
};

⚠️ Типичные ошибки: забыть обновить кэш или использовать слишком короткое время жизни кэша.

Сценарий 2: обработка ошибок API в SSR

Что делать, если API совсем недоступен? Например, ваш сервер для получения данных отправляет HTTP 500.

Решение: В таких случаях вы можете возвращать статическую страницу с ошибкой или использовать SSR для рендеринга пользовательского сообщения.

export const getServerSideProps = async () => {
  try {
    const response = await fetch("https://example.com/api");
    if (!response.ok) {
      throw new Error("Failed to fetch data");
    }
    const data = await response.json();
    return { props: { data } };
  } catch (error) {
    // Обрабатываем ошибку
    return { props: { error: error.message } };
  }
};

// Динамическое отображение ошибки в компоненте
const Page = ({ data, error }: { data?: any; error?: string }) => {
  if (error) {
    return <h1>Ошибка: {error}</h1>;
  }

  return <h1>Данные: {JSON.stringify(data)}</h1>;
};

export default Page;

Сценарий 3: работа с аутентификацией

Допустим, вам нужно показывать разные страницы для авторизованных и неавторизованных пользователей. Как это сделать?

Решение:

  1. Используйте getServerSideProps для проверки сессии пользователя.
  2. Если пользователь не авторизован, перенаправьте его на страницу логина.
export const getServerSideProps = async (context) => {
  const user = await authenticateUser(context.req);
  if (!user) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }
  return { props: { user } };
};

💡 Полезный совет: храните JWT-токены в cookies, чтобы сервер получил доступ к ним при запросе.

Сценарий 4: глобальное состояние и SSR

Когда вы используете глобальное состояние, например Redux, передача состояния между сервером и клиентом может стать вызовом. Ведь данные, загруженные на сервере, нужно "гидратировать" на клиенте.

Решение:

  1. Используйте методы getServerSideProps для получения данных и передачи их в Redux Store.
  2. На клиенте вы можете использовать redux-persist для синхронизации состояния.
import { initializeStore, RootState } from '../store';

export const getServerSideProps = async () => {
  const reduxStore = initializeStore();
  const { dispatch } = reduxStore;

  // Имитация загрузки данных
  await dispatch(fetchDataAction());

  return {
    props: {
      initialReduxState: reduxStore.getState(),
    },
  };
};

// Гидратация на клиенте
const MyComponent = ({ initialReduxState }: { initialReduxState: RootState }) => {
  const store = initializeStore(initialReduxState);
  return (
    <Provider store={store}>
      {/* Ваши компоненты */}
    </Provider>
  );
};

⚠️ Типичные ошибки: забыть передать состояние из getServerSideProps в клиент.

Сценарий 5: сложные динамические маршруты и SEO

Если ваш сайт имеет множество маршрутов, таких как /products/[id], и вы пытаетесь использовать SSR, могут возникнуть проблемы с производительностью.

Решение:

  1. Используйте getStaticPaths для заранее известных маршрутов, а остальные обрабатывайте с помощью SSR.
  2. Настройте маршруты так, чтобы поисковики могли их индексировать.
export const getServerSideProps = async ({ params }) => {
  const { id } = params;
  const data = await fetchProduct(id);

  if (!data) {
    return {
      notFound: true,
    };
  }

  return { props: { data } };
};

Часто задаваемые вопросы

Что выбрать — SSR или SSG?

Если данные изменяются часто или зависят от запроса пользователя (например, профиль), выбирайте SSR. Если данные редко меняются, используйте SSG.

А как насчёт производительности?

Используйте кэширование данных и CDN для отдачи статического контента. Всегда профилируйте серверную часть, чтобы убедиться, что узких мест нет.

Можно ли использовать client-side hydration с SSR?

Да, это стандартная практика. После загрузки HTML пользовательский интерфейс "гидратируется" React-ом для работы с клиентскими событиями. Главное — убедиться, что клиентские данные синхронизированы с серверными.

Опыт внедрения и советы

На практике SSR может значительно улучшить производительность и SEO, но его внедрение требует аккуратного подхода. Старайтесь придерживаться следующих рекомендаций:

  • Всегда профилируйте запросы данных, чтобы минимизировать задержки.
  • Добавляйте обработку ошибок для всех запросов в SSR.
  • Используйте возможности Next.js для комбинирования SSR и SSG.
  • Периодически пересматривайте свою архитектуру, чтобы избежать избыточной сложности.

И, конечно, помните: успех SSR в вашем проекте зависит от баланса между целями производительности и сложностью реализации.

2
Задача
Модуль 3: React, 13 уровень, 9 лекция
Недоступна
Обработка ошибок при недоступности API
Обработка ошибок при недоступности API
3
Опрос
Функция getServerSideProps, 13 уровень, 9 лекция
Недоступен
Функция getServerSideProps
Функция getServerSideProps
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ