Migration Roadmap: як зробити міграцію великого проєкту з Nuxt 2 на Nuxt 3

💡 Усі статті, обговорення, новини про Front-end — в одному місці. Приєднуйтесь до Front-end спільноти!

Всім привіт! Мене звати Володимир Василенко, я Front-end Team Lead у компанії Futurra Group. Ми розробляємо низку освітніх продуктів, зокрема, математичний сервіс MathMaster.

Міграція проєкту з одного стеку технологій на інший — це водночас і точка ризику, і вихід на новий етап для проєкту, а отже, і зона подвійної відповідальності для розробника. Тож потрібно виважено підходити до цього процесу та намагатися мінімізувати ризики, якими він супроводжується.

У своїй статті хочу поділитися досвідом міграції наших проєктів на Nuxt 3, що значно спростило розробку нового функціоналу, прискорило роботу наших застосунків та дозволило вийти на новий рівень якості коду.

Як було до

Зважаючи на стрімкий розвиток проєктів та велику кількість A/B-тестів, що в нас відбуваються постійно, Front-end складова досить часто змінювалась та пройшла декілька етапів еволюції: від HTML/CSS + JQuery до Nuxt 3 SSR + Tailwind CSS.

Основний стек технологій на момент ухвалення рішення про рефакторинг та заміну стеку складався з: Nuxt 2 SSG, Laravel Blade, Bootstrap 5, SCSS, з використанням багатьох бібліотек та пакетів по типу vuex, axios, i18n, OAuth, moment, lottie та інших.

У чому була проблема

У міру розвитку наших продуктів та технологій цього стеку поступово ставало недостатньо для розв’язання поточних задач, а також періодично накопичувалася низка проблем, що потребували вирішення.

Після довгої серії А/В-тестів кодова база ставала все більшою та заплутанішою. Збільшився загальний розмір бандлу та почастішали проблеми з оптимізацією. Особливості побудови архітектури подекуди перешкоджали використанню простих рішень, а відсутність типізації призводила до неявних помилок, що тільки збільшували час розробки.

Також слід брати до уваги масштабування проєктів та збільшення штату девелоперів. Добре побудована архітектура, типізація, перевикористання та патернування логік і компонентів в цьому випадку збільшила б продуктивність команди та підвищила б якість продуктів.

Усе вищенаведене змусило мене задуматись про заміну стеку на більш сучасний і гнучкий, рефакторинг наявної кодової бази та перебудову наших проєктів в цілому.

Перехід до Nuxt 3

Першочергово необхідно було зважити всі ризики та ознайомитись з усією необхідною інформацією. Великою перевагою Nuxt/Vue завжди була досить детальна та проста у використанні документація, яка містить всю необхідну розробнику інформацію.

Ознайомившись з нею та прочитавши низку тематичних статей, переваги заміни старої версії на більш сучасну стали для мене ще більш очевидними.

На момент ухваленя рішення Nuxt 3 мав stable-версію та більшість модулів, які ми використовували, вже були сумісні з Vue 3.

Порівняно з попередньою версією, Nuxt 3 отримав:

  • впровадження останньої версії Vue 3, яка пропонує розширені функції, як-от Composition API та Composables;.
  • Vite — інструмент для створення, збірки та налаштування проєктів. Його основні переваги — швидкість збірки, простота та миттєва гаряча заміна модулів;
  • новий node-сервер Nitro, що має багато корисних функцій;
  • Pinia — нову бібліотеку управління станом для екосистеми Vue;
  • покращену маршрутизацію, автоімпорт та багато чого іншого.

Найсучасніший механізм Nitro Engine у Nuxt 3 покращує практично кожен аспект фреймворку розробки Vue. Оптимізуючи продуктивність, Nitro Engine забезпечує блискавичне завантаження застосунків під час розробки та швидке оновлення під час внесення змін.

Також Nitro додав фреймворку full-stack нових можливостей. Створивши лише каталог server, розробник уже може створювати свою серверну логіку в самому Nuxt 3. Загалом Nuxt 3 тепер ближчий до простого та інтуїтивно зрозумілого full-stack фреймворку.

Через те, що проєкт досить об’ємний та постійно переживає велику кількість А/В-тестів, досить гострою була і проблема гнучкості. Зважаючи на статичну генерацію (SSG) та специфічну серверну архітектуру для зв’язки з Laravel Blade, було досить некомфортно масштабувати проєкт.

Це обмежувало реалізацію певного функціоналу та подекуди призводило до непередбачених труднощів, як-от, наприклад, до проблеми рендерингу та ваги об’ємних за вмістом сторінок залежно від А/В-тест змінної, заплутаної системи роутингу та імпортів, проблеми використання синтаксису Laravel Blade та отримання даних до рендерингу сторінки, втрати даних з LS та Cookies за певних умов тощо.

Composition API та Composables

Революційний Composition API пропонує гнучку структуру коду з можливістю багаторазового використання, що робить роботу розробника менш суворою порівняно з Options API, адже фреймворк стає більш схожим на React.

Основна перевага Composition API полягає в тому, що він дає змогу чистого та ефективного повторного використання логіки у формі композиційних функцій. Він усуває всі недоліки міксинів, основного механізму повторного використання логіки для Options API. Більш гнучка організація коду в Composition API дозволяє краще групувати код на логічні блоки.

Також однією з найважливіших переваг Composition API є його високий рівень абстракції, який полегшує життя розробників, особливо тих, хто не має глибокого досвіду з Vue або Nuxt. Тепер вони можуть використовувати свої знання звичайного JavaScript, не витрачаючи багато зусиль на вивчення синтаксису Vue.

Composables — це, по суті, функції, які інкапсулюють загальну логіку та можуть використовуватися кількома компонентами. Вони забезпечують модульний і гнучкий підхід до створення програм Vue та полегшують підтримку складних проєктів.

Недоліки SSG: чому цей підхід застарів

Маючи SSG (Static Site Generation), нам було досить незручно проводити велику кількість A/B-тестів.

Взагалі статичне генерування вебсайтів довгий час було доволі популярним рішенням. Проте згодом на поверхню стали виходити його суттєві недоліки, які важко ігнорувати, особливо, коли йдеться про великі проєкти:

  1. Обмежена динамічність. SSG чудово справляється з статичними сайтами, але коли потрібно обробляти часті оновлення або велику кількість динамічного контенту, виникають проблеми. Тому підтримувати актуальність такого контенту не завжди ефективно.
  2. Перевантаження. Зберігання та генерація великої кількості статичних файлів може призвести до збільшення обсягу проєкту та ускладнити його управління.
  3. Складність обробки запитів на стороні клієнта. Оскільки SSG генерує статичний контент, обробка запитів користувача стає складною задачею. В реальному часі оновлювати великі обсяги даних може бути неефективно.

Перехід до SSR та його переваги над SSG

SSR (Server-Side Rendering) та SSG (Static Site Generation) — це два різних підходи до генерації контенту для вебсайтів.

Розглянемо переваги SSR над SSG:

  1. Динамічність контенту. SSR дозволяє генерувати контент динамічно на сервері при кожному запиті. Це корисно для сайтів, де контент часто оновлюється, або для вебзастосунків, де потрібна взаємодія з сервером на стороні клієнта.
  2. Прямий доступ до бази даних під час генерації сторінки на сервері. Це важливо для вебзастосунків, які потребують актуальних даних під час завантаження сторінки.
  3. Real-time оновлення. Завдяки SSR можна надавати користувачам актуальні дані в режимі реального часу без необхідності чекати на перегенерацію всього сайту.
  4. Динамічні параметри шляху (Dynamic Path Parameters). SSR дозволяє використовувати динамічні параметри шляху, що дозволяє створювати сторінки з унікальними URL-адресами для різних сутностей.
  5. Контроль генерації контенту і обробки запитів знаходиться на сервері.

Відхід від SSG та вибір на користь серверного рендерингу (SSR) з використанням всіх його переваг зробило Front-end частину нашого проєкту більш гнучкою та надійною.

TypeScript

Однією з причин рефакторингу була необхідність в коді, що буде більш надійним та який буде легше підтримувати. Додавання TypeScript до нашого проєкту — крок, який суттєво полегшив життя розробників.

Використання TypeScript має низку беззаперечних переваг:

  1. Статична типізація. TypeScript дозволяє визначати типи, що дозволяє попереджати виникнення помилок під час розробки.
  2. Прискорена робота. Завдяки підказкам та автодоповненню коду, TypeScript прискорює його написання та виправлення.
  3. Легкий рефакторинг.
  4. Активна спільнота. TypeScript має велику та активну комʼюніті розробників, що означає доступ до різноманітних інструментів та ресурсів.
  5. Сумісність з JavaScript. TypeScript взаємодіє з наявним JavaScript-кодом, дозволяючи поступово впроваджувати його в проєкт.

Словом TypeScript — це інструмент, що робить розробку більш зручною й надійною та, як результат, підвищує якість коду.

Перехід від Bootstrap до Tailwind CSS: технічні аспекти

Bootstrap хоча і став стандартом для фронтенд-розробки, але він не завжди є оптимальним вибором з технічної точки зору. Тож наведу низку технічних аспектів, що можуть впливати на рішення перейти на Tailwind:

  1. Вага та продуктивність. Bootstrap, будучи повноцінним фреймворком, має великий розмір, що може вплинути на час завантаження сторінки. Tailwind же пропонує модульний підхід та можливість генерації легкого CSS, що сприяє меншому розміру збірки та продуктивності.
  2. Архітектура класів та масштабованість. Bootstrap надає велику кількість класів для стилізації, що може призводити до пасивного та важкого коду, особливо у великих проєктах. Tailwind пропонує концепцію Utility-First з акцентом на використанні конкретних класів для стилізації, що полегшує масштабування та обслуговування коду.
  3. Кастомізація та гнучкість. На противагу обмеженим можливостям кастомізації у Bootstrap, Tailwind дозволяє розробникам зберігати більше контролю над дизайном.
  4. Мінімізація використання JavaScript. Bootstrap включає значну кількість JavaScript-коду, який може бути непотрібним для певних проєктів. Tailwind дозволяє розробникам вибирати та використовувати стільки JS, скільки їм потрібно.

Nuxt3 має досить велику сумісність з даним фреймворком. Налаштування Tailwind є доволі простими, а гнучкість кастомізації дозволяє максимально швидко перебудувати проєкт під необхідні налаштування.

Після переходу на Tailwind знову відчуваєш радість життя та отримуєш задоволення від звичайної верстки😄

Pinia

Наступним рішенням було замінити Vuex на Pinia як основний інструмент управління станом. API Pinia простіший та інтуїтивніший, все стає зрозуміло з перших сторінок документації.

Переваги цього інструменту:

  1. Реактивність та швидкодія. Pinia використовує принципи Vue 3.0 та його реактивності. У порівнянні з Vuex, Pinia дозволяє більш ефективно використовувати систему реактивності Vue.
  2. Організація коду. Pinia впроваджує концепцію модульної організації стору, де кожен модуль може мати свій власний стан, мутації та екшени. Це спрощує структуру коду та дозволяє краще масштабувати застосунки.
  3. Завантаження коду. Pinia надає можливість лінивого завантаження модулів стору, що означає, що код для конкретного модуля завантажується лише тоді, коли він справді потрібний. Це сприяє оптимізації завантаження стору.
  4. Типізація та TypeScript. Pinia призначений для роботи із TypeScript «з коробки», надаючи переваги статичної типізації для розробників. Тоді як Vuex також може працювати з TypeScript, Pinia забезпечує більш глибоку інтеграцію та зручний синтаксис.
  5. Persist state. Pinia надає вбудовану підтримку persist state, що дозволяє зберегти стан застосунку навіть після перезавантаження сторінки. Це дуже корисно для тривалих сеансів роботи.

Додаткові зміни

Окрім запровадження наведених вище змін, було виконано значний обсяг рефакторингу та налагодження розгортання.

Ми також реалізували архітектуру розгортання для різних середовищ (DEV, TEST, MODL, PROD) з відповідними конфігураціями. Додали автоматизовані тести для забезпечення якості коду, а також health check для виявлення стану системи та її компонентів.

І внаслідок цього...

Ми оновили проєкт до Nuxt 3, де впроваджено серверний рендеринг (SSR). Оновлення стеку технологій, зокрема перехід на Vue 3/Nuxt 3, TypeScript, Pinia та інші, призвело до значного покращення функціональності та стабільності. Використання Vite/Nitro дозволило зменшити час розробки та деплою. Заміна CSS-фреймворка на Tailwind сприяла прискоренню верстки та полегшенню роботи розробників.

Результатом цих змін став зменшений розмір збірки та покращені показники швидкодії сайту. Упровадження тестового середовища та автотестів сприяло зменшенню кількості багів та підвищило стабільність продакшену.

Проєкт загалом став простішим у масштабуванні, надійнішим та легшим у підтримці. Час, що ми витратили на рефакторинг, вибір та імплементацію нових технологій точно був того вартий, адже результат на всі 100 відсотків відповідає потребам як команди розробників, так і бізнесу.

👍ПодобаєтьсяСподобалось15
До обраногоВ обраному6
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Можно до вас інтреном або джуном? =)

Сумісність з JavaScript. TypeScript взаємодіє з наявним JavaScript-кодом, дозволяючи поступово впроваджувати його в проєкт.

ой-вей, здається джаваскріпт та єсмаскріпт вже не база.. як ті кляті браузери без тайпскріпта досі працюють?. .
ну не знаю.. мабуть грошей заслали комусь..

Відхід від SSG та вибір на користь серверного рендерингу (SSR) з використанням всіх його переваг зробило Front-end частину нашого проєкту більш гнучкою та надійною.

Яким чином це змінює надійність та гнучкість Frontend(те що відбувається на клієнті в браузері, не на сервері)?

У обох випадках, SSR та SSG, дія відбувається на сервері. При SSR під час запиту. При SSG під час збірки проекту. Відрізняється час, коли сторінка була побудована на сервері. Але результат, який віддає сервер буде однаковим. (Звичайно, якщо ваші сторінки не динамічні. Я припускаю, що ні, тому що ви використовували SSG) Ви зробили зміни на серверній частині, а робите висновки про надійність і гнучкість клієнтської частини.

Недоліки SSG: чому цей підхід застарів

Застарів? У чому проявляється саме «застарівання»?

SSG/SSR/ISR — це три різні підходи. У кожного є свої переваги і недоліки. Ви вибірково описали переваги SSR та недоліки SSG. І не згадали про переваги SSG та недоліки SSR. Про ISR взагалі не згадали.

Для різних задач різні підходи працюють краще. Для статично сайту нічого краще SSG не існує.

Дякую за запитання.

Читайте уважно контекст в якому описані ті, чи інші переваги/недоліки. У статті наводиться опис конкретного застосування та поліпшення роботи на проєкті з великою кількістю AB-тестів, асинхронних запитів та динамічного контенту, а не простий опис технологій які існують. Оскільки проєкт мав довгу історію розвитку, то і вимоги до нього постійно змінювались. SSG мав певні переваги в попередніх версіях проєкту ( зважаючи на контекст/ архітектуру / запити бізнесу), але зі збільшенням кількості функціонала та динамічного контенту — цей підхід став не відповідати технічним вимогам. Він застарів в контексті конкретного проєкту, а не як спосіб рендерингу в цілому. Відхід від SSG до SSR як раз і дав змогу вирішити всі ті проблеми, з яким проект зіткнувся до переходу.

Для типових статичних веб-сайтів він залишаеться хорошим рішенням. Підіймати SSR для корпоративного сайту на 3-5 сторінок немає сенсу.

Читаю уважно. Назва абзацу «Недоліки SSG: чому цей підхід застарів».

Всередині:

Взагалі статичне генерування вебсайтів довгий час було доволі популярним рішенням. Проте згодом на поверхню стали виходити його суттєві недоліки, які важко ігнорувати, особливо, коли йдеться про великі проєкти

«Було» та узагальнення про «статичне генерування вебсайтів» натякає на загальну ситуацію з Nuxt, а не про конкретний проект. Також це наштовхує на думку, що з’явився новий підхід, більш популярний, який замінив SSG. Який? «Застарів» — це коли щось використовували і після того з’явився новий підхід, який чимось краще. І тому краще використати новий підхід. Що прийшло на зміну SSG, що він застарів?

У вашому випадку або змінились вимоги і щось стало важливіше. Або ви переглянули свою архітектуру і вирішили, що інший підхід для вас краще. SSR так само існував на Nuxt 2, як і SSG. Це не застарівання. Або, якщо ви наполягаєте про «застарів», то поясніть будь-ласка чому.

Дякую за цікаву статтю. Скільки часу у вас зайняла міграція? Чи були тести на проекті, як ви розуміли що нічого не зламали при міграції? Якщо не було, то чи плануєте додавати?

Приблизно декілька робочих місяців, але робили паралельно з підтримкою минулої версії.
Суттєвих проблем з переходом не мали, головне було заздалегідь продумати архітектуру. Трішки довелось витрачати час на пошуки рішень по реалізації певних логік новими інструментами або аналогами.

Тести були як авто-, так і мануальні. Перевіряли базові логіки, візуал, оптимізацію. Також, проводили тестові запуски на малих об’ємах реальних юзерів.

Підписатись на коментарі