Як структурувати front-end проєкти

Як структурувати front-end проєкти
~8 хв
20 черв 2024
Валерій Стрілець

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

Пласка архітектура

Найпростіша архітектура - це пласка, бо не потребує багато ресурсів. Достатньо створити в корені проєкту потрібні папки, і, наприклад, в components скласти усі існуючі компоненти. Ця архітектура ідеально підійде для маленьких демо-проєктів або PoC (Proof of Concept).

/src
|-- /assets
|   |-- /images
|   |-- /styles
|-- /components
|   |-- BaseButton.vue
|   |-- BaseCard.vue
|   |-- PokemonList.vue
|   |-- PokemonCard.vue
|-- /composables
|   |-- usePokemon.js
|-- /layouts
|   |-- DefaultLayout.vue
|   |-- AdminLayout.vue
|-- /plugins
|   |-- translate.js
|-- /views
|   |-- Home.vue
|   |-- PokemonDetail.vue
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /utils
|   |-- validators.js
|-- /tests
|   |-- ...
|-- App.vue
|-- main.js

Модульна архітектура

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

/src
|-- /core
|   |-- /components
|   |   |-- BaseButton.vue
|   |   |-- BaseIcon.vue
|   |-- /models
|   |-- /store
|   |-- /services
|   |-- /views
|   |   |-- DefaultLayout.vue
|   |   |-- AdminLayout.vue
|   |-- /utils
|   |   |-- validators.js
|-- /assets
|   |-- /images
|   |-- /styles
|   |-- /scss
|-- /plugins
|   |-- translate.js
|-- /tests
|-- /modules
|   |-- /pokemon
|   |   |-- /components
|   |   |   |-- PokemonThumbnail.vue
|   |   |   |-- PokemonCard.vue
|   |   |   |-- PokemonListTemplate.vue
|   |   |   |-- PokemonDetailTemplate.vue
|   |   |-- /models
|   |   |-- /store
|   |   |   |-- pokemonStore.js
|   |   |-- /services
|   |   |-- /views
|   |   |   |-- PokemonDetailPage.vue
|   |   |-- /tests
|   |   |   |-- pokemonTests.spec.js
|   |-- /search
|   |   |-- /components
|   |   |   |-- SearchInput.vue
|   |   |-- /models
|   |   |-- /store
|   |   |   |-- searchStore.js
|   |   |-- /services
|   |   |-- /views
|   |   |-- /tests
|   |   |   |-- searchTests.spec.js
|-- App.vue
|-- main.ts
|-- router.ts
|-- store.ts

Feature Sliced Design

Feature Sliced Design - архітектура, яка дозволяє створювати та розширювати великі та довгострокові проєкти. Використовуючи цей варіант, треба обережно та обдумано вирішувати, куди покласти той чи інший файл, але при цьому Feature Sliced Design дає змогу структурувати файли так, щоб не мати їх десятками та сотнями в одній папці. Головний її підхід в наявності багатьох шарів:

  • app - глобальні файли, наприклад, стилі, провайдери, роутер тощо
  • pages - сторінки для відображення всіх сутностей, фіч та віджетів, які можуть мати свої власні стили, функції тощо
  • entities - папка для бізнес сутностей, таких як User, Order, Product тощо; іншими словами, для всього, що може створювати та редагувати користувач сайту
  • features - зазвичай це папка, яка відповідає за компоненти, наприклад, для відправлення коментарів, додавання до кошика або пошук користувачів, але можуть бути і звичайні js чи ts файли
  • widgets - папка для комбінування сутностей та фіч в цілісні блоки інтерфейсу, такі як IssueList або UserProfile
  • shared - папка для всього, що не пов'язано ні з чим попереднім, ідеально підходить для файлів, які можуть використовуватися по всьому проєкту, наприклад, UI компоненти, глобальні hook/composables, utils тощо
/src
|-- /app
|   |-- App.vue
|   |-- main.js
|   |-- app.scss
|-- /pages
|   |-- Home.vue
|   |-- PokemonDetailPage.vue
|-- /widgets
|   |-- UserProfile.vue
|   |-- PokemonStatsWidget.vue
|-- /features
|   |-- pokemon
|   |   |-- CatchPokemon.vue
|   |   |-- PokemonList.vue
|   |-- user
|   |   |-- Login.vue
|   |   |-- Register.vue
|-- /entities
|   |-- user
|   |   |-- userService.js
|   |   |-- userModel.js
|   |-- pokemon
|   |   |-- pokemonService.js
|   |   |-- pokemonModel.js
|-- /shared
|   |-- ui
|   |   |-- BaseButton.vue
|   |   |-- BaseInput.vue
|   |   |-- Loader.vue
|   |-- lib
|   |   |-- api.js
|   |   |-- helpers.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /tests
|   |-- featureTests.spec.js

Мікрофронтенди

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

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

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

Висновок

Для кожного проєкту треба підібрати влучну архітектуру, яка не буде йому шкодити, адже не для всіх може підійти, наприклад, Feature Sliced Design або модульна архітектура.

АрхітектураПлюсиМінуси
ПласкаЛегко реалізувати, мінімальні налаштуванняВажка у масштабуванні, ускладнюється з ростом проєкту
МодуліЛегка у масштабуванні, інкапсульовані функціїМожливі дублікати файлів, може стати складною
Feature Sliced DesignНаявність багатьох шарів, чітка структураМоже бути складна для розуміння, потребує планування
МікрофронтендиНезалежність від інших частин додаткуВисока складність

Стаття написана на основі матеріалу How to Structure Vue Projects.

поглиблюй свої знання з wannabe school
поглиблюй свої знання з wannabe school
поглиблюй свої знання з wannabe school
поглиблюй свої знання з wannabe school
Свідоме навчання
від практикуючих IT-працівників
Елемент паралаксу
Елемент паралаксу