Он вам не SSR. Nuxt — больше, чем Server-Side Render фреймворк
- пятница, 7 марта 2025 г. в 00:00:06
Привет, Хабр! Я - Frontend Developer в МТС Диджитал. Все чаще и чаще я натыкаюсь на сообщения и комментарии пользователей в различных социальных сетях про Server-Side Rendering.
Обычно эти жалобы о том, кто-то недоволен зависимостью Next.js от Node.js-сервера. Кто-то сталкивается с ограничениями динамического роутинга при статической генерации. Исходя из этого некоторые люди писали в комментариях что-то вроде: "Вы же не ожидали, что SSR-фреймворк решит все проблемы разом?"
Большинство моих коллег с других компаний в принципе не понимают зачем я беру Nuxt почти во все свои проекты и задают вопросы. На первый взгляд это вполне логично. Какой смысл брать SSR фреймворк, если ты выключаешь в нем SSR. На примере Nuxt, SSR можно выключить одним булевым флагом в конфиге:
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false
})
Так или иначе это хорошие и правильные вопросы. Правда как правило их задают люди, которые ранее никогда глубоко не были знакомы с Nuxt и его экосистемой.
Поэтому сегодня давайте я попытаюсь "продать" вам Nuxt со всей его экосистемой. В тоже время чтобы жизнь не казалось мёдом, расскажу про нюансы которые вас ждут.
И первое с чего хочется начать это Nuxt Modules. Что это за зверь такой ? Если вкратце это модульная система, которая позволяет легко добавлять функциональность в проекты без необходимости писать всё с нуля. Она помогает сэкономить приличное кол-во времени вначале вашего пути. Далее я приведу в пример несколько модулей, которые иногда использую сам.
Nuxt image
Хотите одной строчкой подключить удобный механизм работы с изображениями ? Пожалуйста вот вам Nuxt Image. Оптимизация и удобная работа с вашими картинками
<NuxtImg src="/nuxt-icon.png" />
Nuxt Icons
А как насчет уже готовой и удобно интегрированной работы с иконами ? Нет проблем! Вот тебе Nuxt Icons. Более 200,000+ готовых к использованию SVG иконок, почему бы и нет особенно для стартапов.
<Icon name="uil:github" style="color: black" />
i18n
Хочешь чтобы твое приложение использовалось по всему миру ? No problem! Для тебя уже есть готовое решение от i18n
// // nuxt.config.ts
{
modules: [
'@nuxtjs/i18n',
],
i18n: {
locales: [
{ code: 'en', language: 'en-US' },
{ code: 'fr', language: 'fr-FR' }
],
defaultLocale: '',
}
}
Nuxt Color-mode
А что насчет любимой всеми программистами тёмной темы ? Держи пожалуйста, вот тебе Nuxt сolor-mode с уже настроенным автоматическим определением темы, в зависимости от темы пользователя на устройстве (Dark/Light)
И это всё лишь верхушка айсберга модулей! Ну разве это не круто !?
Безусловно все эти модули можно собрать самому. Но здесь они уже готовы и настроены прямо из коробки для тебя и Nuxt. Ты можешь включать и выключать их одной кнопкой в богоподобных NuxtDevTools! Кстати это еще один "+" в копилку к сотням уже существующих модулей
Да, модули действительно отличная штука. А что если нужно быстро стартануть проект и у тебя нет ресурсов на разработку своего UI Kit-а? Кнопки, инпуты и модалки все таки нужны, а настраивать и подгонять под Quasar или упасти боже Vuetify не получается.
Тогда для тебя есть альтернатива от Nuxt. Отличный базовый набор готовых и настраиваемых компонентов.
Если честно, я не любитель готовых UI Kit-ов. Все же на длительной дистанции мне всегда не хватало их гибкости. Но буквально на днях, мне нужно было оперативно запустить небольшой интернет-магазин и здесь Nuxt UI показал себя на полную.
Ладно ладно, понимаю что тебе не хочется тащить готовые модули в свой проект и руки чешутся чтобы написать что-нибудь своё.
Для этого случая у нас есть Nuxt Kit он нужен для создания и управления модулями. Он упрощает процесс разработки Nuxt Modules, предоставляя удобные API для работы с настройками, хуками, файловой системой и другими возможностями фреймворка.
И да, хочу напомнить что мы все еще говорим про "SSR" фреймворк! Это значит что по мимо той малой части которую я перечислил выше, мы еще получаем все плюсы от самого SSR.
Звучит слишком хорошо, но должны же быть какие-то минусы ?
Я считаю что плохо понимаю технологию, если не знаю или не вижу её недостатков. Исходя из этого, Nuxt на первом этапе мне казался идеальным инструментом. Если у тебя сложилось такое же впечатление, я бы хотел снять розовые очки и обсудить проблемы и нюансы.
Повышение требований для новых разработчиков.
Начну пожалуй с очевидного это повышение требований для новых разработчиков. Чтобы хорошо писать SSR, было бы неплохо понимать Node.js. Особенно, если мы говорим про написание своих модулей. Также стоит знать и помнить про "плохой код", который может вызвать утечки памяти.
Риск утечки памяти.
Несмотря на большое кол-во плюсов, в Nuxt следует быть осторожным. Есть большое кол-во подводных камней об которые вы можете споткнуться.
⌛️ setInterval / setTimeout
Чаще всего мы можем вызвать утечки когда используем setInterval на SSR. Именно он является спонсором занимательных посиделок за компьютером в субботу или воскресенье. Что же касается setTimeout, то утечки с ним происходят крайне редко.
// Пример
export default defineEventHandler(() => {
setInterval(() => {
console.log("Интервал работает!");
}, 1000); // Этот интервал никогда не очищается !!!
});
Советы и рекомендации:
Используйте setTimeout, если код должен выполняться однократно;
при необходимости интервалов — очищайте их с clearInterval();
таймеры лучше запускать на клиенте, а не на сервере.
🚀 Ref / Computed / Watch
Также утечку памяти зачастую вызывает создание или вызов Ref / Computed / Watch ВНЕ setup.
// Пример с computed
const globalRef = ref(10);
const globalComputed = computed(() => globalRef.value * 2); // Глобальный computed
export default defineComponent({
setup() {
console.log(globalComputed.value); // Будет существовать в памяти навсегда!
return { globalComputed };
}
});
Как это можно исправить ?
// Определяем computed внутри setup()
export default defineComponent({
setup() {
const localRef = ref(10);
const localComputed = computed(() => localRef.value * 2); // Авто-очищение
return { localComputed };
}
});
Советы и рекомендации:
Не создавай ref, computed и watch вне setup(), иначе они останутся в памяти навсегда;
определяй их внутри setup(), чтобы они автоматически очищались при уничтожении компонента;
Про утечки памяти соберу отдельную большую статью с примерами. В этом же материале даю базовый джентельменский набор 🤵♂️
Версионирование и сложности при миграции.
Какой Frontend разработчик не сталкивался с болью при миграции/обновлении JS библиотек. Даже если версия одной либы обновится, мы вполне можем сломать какую-то часть приложения. А что если мы переезжаем с Vue 2 на Vue 3 и у нас есть зависимости от десятков различных библиотек + большинство из которых не поддерживают Vue 3...
С Nuxt ситуация обстоит лучше. Миграция с Nuxt 2 на Nuxt 3 была непростой, но за счет Nuxt Bridge, который является неким промежуточным шагом перед миграцией это давалось легче.
Тем не менее проблема не исчезает, в Nuxt 3 произошло: изменение API, поменялась структура проекта, удалены некоторые устаревшие хуки и это лишь малая того, что вам нужно учесть при переезде. Миграцию на Nuxt 4 нам обещают легче чем на 3 версию, но как будет на самом деле увидим в будущем.
Еще немного про минусы.
Еще в этом праздник жизни нужно учесть: правильную работу с контекстом и asyncData, дебаг ошибок и утечек памяти, правильное понимание работы хуков. И это я еще не упомянул здесь про сам SSR!
Многие воспринимают Nuxt исключительно как SSR-фреймворк. Но в реальности Nuxt — это не просто серверный рендеринг, а мощная экосистема с гибкой модульной системой.
Очень надеюсь, что в будущем Nuxt получит ещё больше внимания как универсальный мета-фреймворк для Vue 🤞🏻