Часть 2

В моем последнем посте я рассмотрел некоторые основы рендеринга на стороне клиента (CSR) и рендеринга на стороне сервера (SSR). Проверьте это здесь, если вы не знакомы:



Create React App был примером приложения CSR, а Next.js был введением в мир SSR. Как уже отмечалось, Next.js выводит весь рендеринг на сервере на новый уровень с множеством опций, поэтому в этом посте будут объяснены некоторые его возможности с вариантами использования.

🗒 быстрое примечание: вы можете погуглить "CRA SSR", и у вас много работы. Я просто говорю о базовой функциональности "из коробки".

Предварительный рендеринг в Next.js

Next.js фокусируется на предварительном рендеринге, что является более общим термином, чем SSR. Документы описывают, что предварительный рендеринг включает в себя 2 вещи:

  1. Рендеринг на стороне сервера (SSR), как и в предыдущем посте
  2. Статическая генерация (SSG = статическая генерация сайта)

SSG похож на SSR в том, что сервер отвечает за предварительный рендеринг HTML (без CSR!), Но это происходит во время сборки, т.е. npm run build для нестандартного проекта Next.js. Вообще говоря, вы должны статически создавать страницы, которые будут одинаковыми для всех клиентов (маркетинговые страницы, страницы сообщений в блогах и т. Д.).

Почему вещи, созданные во время сборки, великолепны?

  1. Когда вы запускаете команду build, это выходит за рамки рабочего процесса, когда кто-то действительно посещает ваш сайт, поэтому нет проблем, если это займет немного времени.
  2. После того, как ваши страницы SSG созданы, они могут размещаться в CDN. Это означает, что HTML находится в периферийных местоположениях по всему миру, и браузер очень быстро запрашивает и отображает их для пользователя.
  3. Вашему веб-серверу не нужно будет выполнять какую-либо работу для статически сгенерированных страниц, обслуживаемых из сети CDN, поэтому вам не нужно беспокоиться о его производительности в этом контексте.

Эти преимущества сочетают в себе преимущества CSR и SSR, как я описал в моем последнем посте, а именно сервер выполняет работу по созданию фактического HTML, но мы все равно можем поместить его в CDN. Тема в документации Next.js действительно становится такой: «Если вы можете использовать SSG для конкретного случая использования, сделайте это».

Документация Next.js великолепна, но была пара концепций, которые сбили меня с толку относительно более интересных вариантов SSG. Приведенные ниже варианты использования - это попытка прояснить некоторые вещи.

Код

Примеры кода можно найти в этом репо здесь https://github.com/neightjones/next-ssr-ssg-blog

Пример использования 1: простая маркетинговая страница

Этот пример ясен. Допустим, у нас есть страница О нас, состоящая из компонента без извлечения данных или чего-то еще - просто статическая страница. Загляните на страницу AboutUs в репо.

Мы определенно хотим, чтобы он был статически сгенерирован во время сборки, потому что это настолько просто, насколько это возможно. Каждый пользователь будет видеть одно и то же, поэтому его можно обслуживать прямо из CDN. К счастью, SSG используется по умолчанию для Next.js. Когда вы запустите npm run build, она превратится в простую HTML-страницу, готовую к работе.

Пример использования 2: список сообщений в блоге

Теперь, когда мы вышли за рамки случая 1, все более сложные случаи будут включать в себя какой-то динамический контент. Это может означать 2 вещи:

  1. Некоторый контент на странице со временем будет меняться (например, вы добавляете новую запись в свой блог, поэтому теперь на странице, на которой они перечислены, должна отображаться новая).
  2. Набор существующих страниц расширяется за счет нового содержания (например, теперь, когда вы добавили новое сообщение в блог, у вас, вероятно, будет дополнительная страница, например /posts/<new_post_id>

Давайте сначала сосредоточимся на компоненте, чтобы перечислить все наши сообщения в блоге. Можно ли использовать рендеринг на стороне сервера в Next.js? В конце концов, когда добавляются сообщения в блог и я обновляю свой браузер, я хочу видеть все самые новые сообщения. С SSR мой запрос страницы списка будет каждый раз создаваться на сервере, который затем всегда будет получать новейший контент из базы данных (или файловой системы… однако мои сообщения в блоге сохраняются). SSR даст вам желаемый результат, но Next.js может добиться большего.

Введите Статическая генерация с данными. Next.js имеет встроенный способ создания SSG, который полагается на внешние данные во время сборки, поэтому вы можете предварительно собрать все необходимое и поместить его в CDN. Все, что вам нужно сделать, это реализовать async функцию с именем getStaticProps в одном из компонентов вашей страницы.

Я не буду изобретать велосипед, но вот простой пример. Ознакомьтесь с документацией здесь для более подробного описания. Ссылка на компонент репо здесь.

Поскольку getStaticProps реализован, Next будет знать, что нужно запустить getBlogs во время сборки (и на сервере), что создаст окончательный HTML-код, отображающий список сообщений в блоге. Эта страница может находиться в сети CDN, поэтому ее можно будет быстро открыть и отобразить в браузере.

Возможно, нам также понадобится одна страница для каждого сообщения в блоге, например /posts/<some_post_id>. Next.js также упрощает создание этих путей и страниц статически во время сборки. Итак, если у вас есть 3 сообщения в блоге с идентификаторами 1, 2 и 3, вы можете использовать SSG для предварительного рендеринга 3 соответствующих страниц блога со всеми установленными путями (/posts/1, /posts/2 и /posts/3). Для этого вы реализуете getStaticProps вместе с getStaticPaths. Нет необходимости воссоздавать документы, так что проверьте это здесь.

Благодаря статической генерации с данными теперь мы можем создавать все страницы и маршруты наших сообщений в блоге во время сборки, и это здорово. Что происходит, когда вы пишете новый пост в блоге? Все было создано только во время сборки, поэтому вы не увидите новую запись, если обновите страницу в браузере. В этом случае лучше всего перестроить сайт, чтобы стал доступен новейший контент. Это может показаться немного раздражающим, но контент не меняется слишком часто, и вы можете автоматизировать процесс сборки / развертывания для своего блога.

Однако необходимость перестроения и развертывания, безусловно, вызывает вопрос - в какой момент контент меняется слишком быстро или становится слишком в размере, чтобы оправдать постоянную перестройку вашего сайта ? Еще один фактор, который следует учитывать, - какие пользователи могут получить доступ к разному контенту? Что касается примера блога, я предполагаю, что он полностью общедоступен. Но если есть какие-то личные данные для каждого пользователя, мы не захотим предварительно визуализировать все с использованием пользовательских данных. Следующий вариант использования демонстрирует еще пару трюков SSG в Next.js, чтобы справиться с большей сложностью.

Пример использования 3: рост сайта электронной коммерции

Этот пример основан на этом сообщении в блоге от Vercel (людей, которые создают Next.js). Я подведу итоги, но рекомендую также прочитать их пост полностью.

Мы реализовали стратегию предварительного рендеринга для вашего блога с помощью статической генерации с данными, описанной выше. Теперь у вас есть быстрорастущий сайт электронной коммерции. На этой неделе будут добавлены тысячи продуктов, и существующие списки продуктов будут несколько часто меняться (цены, инвентарь и т. Д.).

Давайте сначала сосредоточимся на странице со списком продуктов (например, /products), а также на отдельных страницах продуктов (например, /products/1). Что произойдет, если мы попытаемся применить технику статической генерации с данными?

  1. Мы столкнемся с проблемой при добавлении продуктов на сайт. Нам пришлось бы перестраивать сайт очень часто, и это заняло бы много времени, потому что мы статически генерировали тысячи страниц с товарами. Это невозможно.
  2. Точно так же у нас будет проблема при изменении продуктов. Опять же, нам придется перестроить сайт, чтобы отразить изменение продукта для клиентов. Тоже неосуществимо.

Мы хотим, чтобы клиенты видели самые свежие данные, чтобы они могли покупать товары. Должны ли мы наконец использовать SSR для обеспечения актуальности данных по каждому запросу?

Оказывается, наверное, нет! В Next.js есть концепция под названием Добавочная статическая генерация, которая помогает динамическим сайтам, таким как наш магазин электронной коммерции, оставаться в мире статической генерации (Next.js делает все возможное, чтобы помочь нам использовать SSG!). Поскольку я все больше и больше работал с Next.js, я обнаружил, что это один из самых крутых вещей.

Случай 1. Добавление страниц продукта в течение срока службы статически созданной сборки

Допустим, мы статически сгенерировали наш сайт электронной коммерции со 100 товарами. Но теперь на этой неделе будет перечислено 1000 новых продуктов. Мы можем использовать ключ с именем fallback внутри нашего вызова getStaticPaths (Я тоже связал это выше, но это тот случай, когда вы используете SSG и автоматически генерируете все пути и страницы продуктов во время сборки).

Обычно fallback будет false. Это делает то, что вы ожидаете - любой путь, который не был создан во время сборки, вернет 404. Это хорошо, потому что если кто-то перейдет к /products/<non-existent product_id>, 404 будет правильным. Однако вы можете разблокировать особое поведение, если для fallback установлено значение true. Ознакомьтесь с официальными fallback: true документами.

С true 404 не будет возвращаться для неизвестного пути. Вместо этого вы получите указание от Далее, что вы должны отобразить «Резервную» страницу (по сути, страницу загрузки). Тем временем сервер лениво сгенерирует для пользователя соответствующую страницу. Вот рабочий процесс:

  1. Я добавляю на сайт товар с новым идентификатором 5000
  2. Пользователь пытается перейти на страницу /products/5000, но ее еще нет (конечно, нет, потому что я только что добавил продукт)
  3. Браузер отобразит для пользователя страницу возврата / загрузки (без ошибок или чего-то подобного)
  4. Сервер генерирует HTML-страницу для продукта 5000, а затем добавляет 5000 к своему набору известных путей (теперь страницу продукта 5000 можно кэшировать в CDN)
  5. Теперь пользователь увидит страницу продукта вместо запасного варианта.
  6. Для всех будущих запросов на этот продукт в течение всего срока его развертывания продукт 5000 готов к работе - работу нужно было выполнить один раз, лениво!

Случай 2. Обновление страниц продукта в течение срока службы статически созданной сборки

В Next.js. этот случай еще проще. Это называется «Постепенное статическое повторное создание», поскольку оно заключается в периодическом повторном создании страницы после первоначальной сборки.

Все, что вам нужно сделать, это добавить ключ с именем revalidate в вызов getStaticProps. Например, revalidate: 60 (60 секунд) будет иметь следующий рабочий процесс:

  1. Изначально создается страница для продукта X. Если он был построен лениво, пользователь увидит эту страницу с новым продуктом в момент времени 0.
  2. Допустим, через 1 секунду цена товара изменилась.
  3. Теперь, примерно через 30 секунд, другой пользователь переходит на страницу продукта X. Тем не менее, он все равно будет видеть старую информацию о ценах, потому что регенерация происходит только каждые 60 секунд.
  4. По прошествии полной минуты другой пользователь запрашивает страницу, и Next знает, что нужно регенерировать страницу продукта X, что приведет к новым ценам (хотя для этого пользователя он все равно может снова получить старую страницу, но он предупредил Далее для создания нового)

Теперь наш сайт электронной коммерции генерируется статически, но при этом у нас есть динамические элементы, включая добавление новых продуктов и обновление продуктов! Это отличные новости - Next дает нам лучшее из обоих миров в этих сценариях.

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

Примечание о корзине для покупок на сайте электронной торговли

Обратите внимание, что все, что обсуждалось выше, касалось только общедоступной информации, которую могли видеть все. Но корзина актуальна только для конкретного пользователя. Таким образом, в лучшем случае вы можете отобразить некоторые части страницы, но в конечном итоге данные о том, что у пользователя есть в ее корзине, должны быть найдены во время запроса. При желании здесь вы можете использовать SSR, но тот же пост Vercel рекомендует статическую генерацию без данных + выборку на стороне клиента.

Это означает, что Next будет статически генерировать общие части страницы корзины покупок (макет, стиль и т. Д.), Которые можно кэшировать в CDN. Затем браузер должен будет запросить сведения о корзине с сервера во время запроса. Это предпочтительнее SSR из-за производительности - если пользователь перейдет к своей корзине, он очень быстро увидит некоторое содержимое с загрузкой пользовательского интерфейса для фактических сведений о корзине. С SSR ничего не будет на странице, пока не будет построена вся корзина. Важно отметить, что в данном случае это вся личная информация о пользователе, поэтому мы можем игнорировать любую оптимизацию SEO и вместо этого оптимизировать для пользователя, который видит что-то очень быстро.

В Next.js вы можете выбрать, какие стратегии предварительного рендеринга и выборки данных вы хотите использовать для каждой страницы, так что вы можете использовать гибридный подход. Также обратите внимание на Vercel. Они являются создателями Next.js, и с ними очень легко развернуть приложение Next.