Изучите Nuxt с коллекцией из 100+ советов!

Режимы рендеринга

Узнайте о разных режимах рендеринга, доступных в Nuxt.

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

И браузер, и сервер могут интерпретировать код JavaScript для преобразования компонентов Vue.js в HTML-элементы. Этот шаг называется рендеринг. Nuxt поддерживает как универсальный, так и клиентский рендеринги. У этих двух подходов есть преимущества и недостатки, которые мы рассмотрим.

По умолчанию Nuxt использует универсальный рендеринг, чтобы обеспечить лучший пользовательский опыт, производительность и оптимизировать индексацию поисковыми системами, но вы можете переключать режимы рендеринга с помощью одной строки конфигурации.

Универсальный Рендеринг

Когда браузер запрашивает URL-адрес с включенным универсальным (серверным + клиентским) рендерингом, сервер возвращает браузеру полностью отрисованную HTML-страницу. Независимо от того, была ли страница сгенерирована заранее и кэширована или отрисовывается налету, в какой-то момент Nuxt запустил код JavaScript (Vue.js) в среде сервера, создав HTML-документ. Пользователи сразу получают контент нашего приложения, в отличие от рендеринга на клиенте. Этот шаг аналогичен традиционному рендерингу на сервере, выполняемому приложениями PHP или Ruby.

Чтобы не потерять преимущества метода рендеринга на клиенте, такие как динамические интерфейсы и переходы страниц, клиент (браузер) загружает код JavaScript, который запускается на сервере в фоновом режиме после загрузки HTML-документа. Браузер снова интерпретирует его (отсюда и универсальный рендеринг), а Vue.js берет на себя управление документом и обеспечивает интерактивность.

Процесс, когда статичная страница становится интерактивной в браузере, называется "Гидратация".

Универсальный рендеринг позволяет Nuxt-приложению обеспечить быструю загрузку страницы, сохраняя при этом преимущества рендеринга на клиенте. Более того, поскольку контент уже присутствует в HTML-документе, поисковые роботы могут индексировать его без дополнительных затрат.

Пользователи могут получить доступ к статическому содержимому, когда HTML-документ загружен. Затем гидратация обеспечивает интерактивность страницы.

Преимущества рендеринга на сервере:

  • Производительность: Пользователи могут получить немедленный доступ к содержимому страницы, поскольку браузеры могут отображать статический контент гораздо быстрее, чем контент, сгенерированный JavaScript. В то же время Nuxt сохраняет интерактивность веб-приложения, когда происходит процесс гидратации.
  • Поисковая оптимизация: Универсальный рендеринг доставляет все HTML-содержимое страницы в браузер как классическое серверное приложение. Поисковые роботы могут напрямую индексировать содержимое страницы, что делает универсальный рендеринг отличным выбором для любого контента, который вы хотите быстро проиндексировать.

Недостатки рендеринга на сервере:

  • Ограничения разработки: Среды сервера и браузера не предоставляют одни и те же API, и может быть сложно написать код, который мог бы беспрепятственно выполняться на обеих сторонах. К счастью, Nuxt предоставляет рекомендации и специальные переменные, которые помогут вам определить, где выполняется фрагмент кода.
  • Стоимость: Чтобы отображать страницы «на лету», должен быть запущен сервер. Это добавляет ежемесячные расходы, как и у любого традиционного сервера. Однако количество вызовов сервера значительно сокращается благодаря универсальному рендерингу, когда браузер берет на себя навигацию на стороне клиента. Снижение затрат возможно за счет использования пограничного рендеринга.

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

Дополнительные примеры написания кода Vue без несоответствия гидратации смотрите в документации Vue.
При импорте библиотеки, которая использует API браузера и имеет побочные эффекты, убедитесь, что импортирующий ее компонент вызывается только на стороне клиента. Бандлеры не обрабатывают импорт модулей, содержащих побочные эффекты.

Рендеринг на клиенте

Из коробки традиционное Vue.js приложение рендерится в браузере (или на клиенте). После того, как браузер загрузит и спарсит весь JavaScript код, содержащий инструкции для создания текущего интерфейса, Vue.js генерирует HTML-элементы.

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

Преимущества рендеринга на клиенте:

  • Скорость разработки: При работе полностью на клиенте нам не нужно беспокоиться о совместимости кода с сервером, например, при использовании API, доступного только для браузера, такого как объект window.
  • Дешевле: Запуск сервера увеличивает стоимость инфраструктуры, поскольку вам потребуется работать на платформе, поддерживающей JavaScript. Мы можем размещать клиентские приложения на любом статическом сервере с файлами HTML, CSS и JavaScript.
  • Оффлайн: Поскольку код полностью выполняется в браузере, он может продолжать работать, даже если интернет недоступен.

Недостатки рендеринга на клиенте:

  • Производительность: Пользователю приходится ждать, пока браузер загрузит, проанализирует и запустит файлы JavaScript. В зависимости от сети, в которой выполняется загрузка, и устройства пользователя, на котором выполняется анализ и выполнение, это может занять некоторое время и повлиять на пользовательский опыт.
  • Поисковая оптимизация: Индексирование и обновление контента, доставленного посредством рендеринга на клиенте, занимает больше времени, чем при обработке HTML-документа, отрисованного на сервере. Это связано с недостатком производительности, который мы обсуждали, поскольку поисковые роботы не будут ждать полной визуализации интерфейса при первой попытке индексировать страницу. Вашему контенту потребуется больше времени, чтобы отобразиться и обновиться на страницах результатов поиска с рендерингом полностью на клиенте.

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

Вы можете включить рендеринг только на клиенте с помощью Nuxt в вашем nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})
Если вы успользуете ssr: false, вы должны поместить в ~/app/spa-loading-template.html HTML-файл с некоторым HTML-кодом, который вы хотите использовать для рендеринга экрана загрузки, который будет отображаться до тех пор, пока ваше приложение не будет гидрировано.
Узнать больше SPA Loading Template.
Посмотрите видео Александра Лихтера про Создание чистого SPA с Nuxt!?.

Развертывание статичного приложения, отрисованного на стороне клиента

Если вы размещаете приложение на статичном хостинге с помощью команд nuxi generate или nuxi build --prerender, то по умолчанию Nuxt будет рендерить каждую страницу как отдельный статичный HTML-файл.

Если вы используете рендеринг полностью на клиенте, тогда это может быть ненужно. Возможно, вам понадобится только один index.html файл, плюс запасные 200.html и 404.html, которые вы можете указать своему статическому веб-хосту для обслуживания всех запросов.

Чтобы добиться этого, мы можем поменять способ рендеринга маршрутов. Просто добавьте это к вашим хукам в nuxt.config.ts:

nuxt.config.ts
export default 
defineNuxtConfig
({
hooks
: {
'prerender:routes' ({
routes
}) {
routes
.
clear
() // Не создает никаких маршрутов (кроме значений по умолчанию)
} }, })

Это создаст три файла:

  • index.html
  • 200.html
  • 404.html

200.html и 404.html могут быть полезны для используемого вами хостинг-провайдера.

Гибридный рендеринг

Гибридный рендеринг допускает разные правила кэширования для каждого маршрута, используя правила маршрутизации, и решает, как сервер должен отвечать на новый запрос по заданному URL.

Раньше каждый маршрут/страница Nuxt-приложения и сервер должны были использовать одинаковый режим рендеринга, универсальный или клиентский. В различных случаях некоторые страницы должны быть созданы во время сборки, в то время как другие должны быть отрисованы на клиенте. Например, подумайте о контентных сайтах с админ-частью. Каждая страница с контеном должна быть в первую очередь статической и генерироваться один раз, но админ-часть требует регистрации и ведет себя скорее как динамическое приложение.

Nuxt включает в себя правила маршрутизации и поддержку гибридного рендеринга. Используя правила маршрутизации, вы можете определить правила для группы маршрутов nuxt, меняя режим рендеринга или назначая стратегию кэширования, основанную на маршруте!

Nuxt-сервер будет автоматически регистрировать соответствующие middleware и оборачивать маршруты обработчиками кэша, используя слой кеширования Nitro.

nuxt.config.ts
export default 
defineNuxtConfig
({
routeRules
: {
// Домашняя страница предварительно отрисовывается во время сборки '/': {
prerender
: true },
// Страница продуктов создается по требованию, повторно проверяется в фоновом режиме, кэшируется до изменения ответа API '/products': {
swr
: true },
// Страница продукта создается по требованию, повторно проверяется в фоновом режиме, кэшируется на один час (3600 секунд) '/products/**': {
swr
: 3600 },
// Страница сообщений в блоге создается по требованию, повторно проверяется в фоновом режиме, кэшируется на CDN на один час (3600 секунд) '/blog': {
isr
: 3600 },
// Страница сообщения в блоге создается по требованию до следующего развертывания, кэшируется на CDN '/blog/**': {
isr
: true },
// Панель управления администратора рендерится только на клиенте '/admin/**': {
ssr
: false },
// Добавляет CORS-заголовки на маршрутах API '/api/**': {
cors
: true },
// Перенаправляет старые URL-адреса '/old-page': {
redirect
: '/new-page' }
} })

Правила маршрутизации

Вы можете использовать следующие свойства:

  • redirect: string - Определяет перенаправления на сервере.
  • ssr: boolean - Отключaет серверный рендеринг HTML для разделов вашего приложения, чтобы они рендерились только в браузере.ssr: false.
  • cors: boolean - Автоматически добавляет cors-заголовки с cors: true - вы можете настроить вывод, переопределив с помощью headers.
  • headers: object - Добавляет определенные заголовки в разделы вашего сайта, например, в ассеты.
  • swr: number | boolean - Добавляет заголовки кэша к ответу сервера и кэширует его на сервере или обратном прокси-сервере для настраиваемого TTL (time to live - времени жизни). Настройка Nitro node-server способна кэшировать полный ответ. По истечении срока жизни (TTL) будет отправлен кэшированный ответ, а страница будет перегенерирована в фоновом режиме. Если импользуется true, будет добавлен заголовок stale-while-revalidate без MaxAge.
  • isr: number | boolean - Поведение схоже с swr, за исключением того, что мы можем добавить ответ в кеш CDN на платформах, которые это поддерживают (в настоящее время Netlify или Vercel). Если используется true, контент сохраняется до следующего развертывания внутри CDN.
  • prerender: boolean - Предварительно отрисовывает маршруты во время сборки и включает их в сборку как статические ресурсы.
  • experimentalNoScripts: boolean - Отключает рендеринг скриптов Nuxt и подсказок ресурсов JS для разделов вашего сайта.
  • appMiddleware: string | string[] | Record<string, boolean> - Позволяет вам определить middleware, которое должно или не должно запускаться для путей к страницам в части Vue вашего приложения (то есть не для ваших маршрутов Nitro).

По возможности правила маршрутизации будут автоматически применяться к собственным правилам платформы развертывания для достижения оптимальной производительности (в настоящее время поддерживаются Netlify и Vercel).

Обратите внимание, что гибридный рендеринг недоступен при использовании nuxt generate.

Примеры:

Nuxt Vercel ISR

Пример Nuxt-приложения с гибридным рендерингом, развернутом на Vercel.

Пограничный рендеринг

Пограничный рендеринг (Edge-Side Rendering - ESR) — это мощная функция, представленная в Nuxt, которая позволяет отображать ваше приложение Nuxt ближе к вашим пользователям через пограничные серверы сети доставки контента (CDN). Используя ESR, вы можете обеспечить повышенную производительность и сокращение задержек, тем самым обеспечивая улучшенный пользовательский опыт.

При использовании ESR процесс рендеринга переносится на «край» сети — пограничные серверы CDN. Обратите внимание, что ESR — это скорее цель развертывания, чем реальный режим рендеринга.

Когда делается запрос страницы, вместо того, чтобы дойти до исходного сервера, он перехватывается ближайшим пограничным сервером. Этот сервер генерирует HTML для страницы и отправляет его обратно пользователю. Этот процесс минимизирует физическое расстояние, которое должны пройти данные, уменьшая задержку и ускоряя загрузку страницы.

Пограничный рендеринг возможен, благодаря Nitro - серверному движку - который обеспечивает работу Nuxt 3. Он предлагает кроссплатформенную поддержку Node.js, Deno, Cloudflare Workers и других.

Текущие платформы, на которых вы можете использовать ESR:

  • Cloudflare Pages с нулевой конфигурацией с использованием git-интеграции и команды nuxt build
  • Vercel Edge Functions с использованием команды nuxt build и переменной окружения NITRO_PRESET=vercel-edge
  • Netlify Edge Functions с использованием команды nuxt build и переменной окружения NITRO_PRESET=netlify-edge

Обратите внимание, что гибридный рендеринг можно использовать при использовании пограничного рендеринга с правилами маршрутизации.

Вы можете изучить примеры с открытым исходным кодом, развернутые на некоторых платформах, упомянутых выше:

Nuxt Todos Edge

Приложение со списком дел с аутентификацией пользователей, SSR и SQLite.

Atinotes

Редактируемый сайт с универсальным рендерингом на Cloudflare KV.