Последние годы удалось поработать над несколькими большими и не очень проектами с использованием разных back-end и front-end фреймворков. Сталкивался с разными проблемами, возникавшими по мере роста приложения.
Сейчас могу сделать вывод из того, какие решения были удачными, а какие — не очень.
Используя накопленный опыт, задался целью собрать все лучшие решения, на мой взгляд, и создать свою основу для SPA.
Как создавать сайт на Laravel или что такое SPA, я рассказывать не буду. Такой информации хватает в интернете. Эта статья рассчитана на более-менее опытных разработчиков, поэтому некоторые детали я упущу.
Кому не терпится, в конце статьи ссылка на мой репозиторий на гитхабе.
Основными технологиями были выбраны Laravel и Vue.js + Vuex так как это мой основной стек.
Для быстрой разработки взял UI Kit — ElementUI.
Главная цель
Создать основание для среднего и большого проекта которое:
- поможет избежать жёсткой сцепленности модулей
- будет понятное для программиста c небольшим опытом
- поможет избежать дублирования кода
- будет легко расширяться
- уменьшит время старта проекта
- уменьшит время поддержки проекта и навигации по коду
- заложит основу для написания качественного кода
Чтобы максимально облегчить себе жизнь, не путаться в проекте, нужно правильно эго структурировать. Изначально приложение должно быть поделено на уровни ответственности, такие как пользовательский интерфейс, база данных, бизнес логика.
Дальше каждый слой следует разделить сначала по функциональности, а потом уже каждый функциональный модуль — соответственно выбранному паттерну.
Вдохновляясь философией DDD, решил и фронт-енд и бэк-енд разделить на смысловые модули. Но это не те классические домены, что описывает Эванс. Его модель тоже не идеальна. В любом приложении со временем всегда появляются связи между компонентами — те же отношения между моделями.
Модели оставил отдельным слоем, потому, что они как бы дублируют базу данных, со всеми ее связями.
На фронте создал каталог resources/js/modules, в котором и будут находиться разные модули. В каждом будет api — методы для работы с бэк-ендом, components — все компоненты и страницы, store — хранилище, и routes.
{moduleName}/
¦
+-- routes.js
¦
+-- api/
¦ L-- index.js
¦
+-- components/
¦ +-- {ModuleName}List.vue
¦ +-- {ModuleName}View.vue
¦ L-- {ModuleName}Form.vue
¦
L-- store/
+-- store.js
+-- types.js
L-- actions.js
В resources/js создана папка core, где помещены основные компоненты системы.
Также есть папки bootstrap и includes для настройки дополнительных библиотек и утилит соответственно.
В проекте используется динамическая погрузка моделей. А именно в core/routes и в core/states мы подгружаем соответствующие файлы роутов и хранилищ автоматом (ничего прописывать не надо).
Вот пример как были подгружены store.js с разных модулей автоматически.
// Load store modules dynamically.
const requireContext = require.context('../../modules', true, /store\.js$/)
let modules = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)]
)
.reduce((modules, [path, module]) => {
let name = path.split('/')[0]
return { ...modules, [name]: module.store }
}, {})
modules = {...modules, core}
export default new Vuex.Store({
modules
})
На бэк-енде в каталоге app будут аналогичные модули. Каждый модуль будет содержать папки Controllers, Requests, Resources. Файл с роутами тоже вынесен сюда — routes_api.php.
{ModuleName}/
¦
+-- routes_api.php
¦
+-- Controllers/
¦ L--{ModuleName}Controller.php
¦
+-- Requests/
¦ L--{ModuleName}Request.php
¦
L-- Resources/
L-- {ModuleName}Resource.php
Другие шаблоны проектирования типа events, jobs, polices и т.п. не будут включены в модули, так как они используются реже и логичнее их держать отдельным слоем.
Все манипуляции с динамической загрузкой модулей сделаны для того, чтобы между ними било минимальное зацепление. Это позволяет без последствий добавлять и удалять модули. Теперь можно сделать artisan make команду для создания такого модуля. С ее помощью мы сможем быстро наполнить проект нужными сущностями вместе с CRUD функциональностью.
Выполнив команду
php artisan make:module {ModuleName}
, у нас появятся все нужные файлы включая модель и миграции для работы полноценного CRUD. Вам останется только выполнить миграции php artisan migrate
и все будет работать. Скорее всего вам понадобиться добавить дополнительные поля, поэтому перед миграцией не забудьте добавить их в модель, миграцию, а также, вывести во vue.В данном шаблоне для аутентификации использовалась технология JWT-Auth, но возможно она избыточная и стоит переделать на Laravel Sanctum. В свою очередь На фронт-енде используется vue-auth, она позволяет легко управлять авторизацией пользователей и ролями.
В дальнейшем хотелось бы улучшить систему. Добавить глобальную шину событий, подключить websockets. Добавить тесты. Возможно в отдельных ветках сделать вариант с управлением ролями или создать ветки с другими UI Kit. Было бы хорошо, услышать рекомендации, замечания.
Изначально данный шаблон разрабатывался для своих нужд, но теперь надеюсь он станет полезным и для других пользователей.
Весь код можно посмотреть в моем репозиторие на гитхабе.
alex_kulkoff
Автоимпорт в store, сводит с ума IDEшку.
Yurich_T Автор
Главное типы подгрузить, а с этим никаких проблем.