Русский
Русский
English
Статистика
Реклама

Микросервисы во фронтенде

image


Привет, Хабр!
Микросервисы уже давно стали классикой в бэкенд архитектуре, но в отличие от бэкенда, во фронтенде одновременно можно использовать только один фреймворк. Это порождает неудобства при масштабировании и переиспользовании модулей. Микросервисный подход избавляет от необходимости придерживаться конкретного фреймворка и дает возможность программисту сосредоточиться на конкретном модуле с использованием наиболее удобных для него инструментов. Мы не пропагандируем расширение зоопарка технологий и использование каждого фреймворка необходимо тщательно обдумать, прежде чем внедрять. Подробнее в статье от разработчика команды BSL gyk007


Сразу спойлер уже готов мини фреймворк, который легко позволит вам это сделать.


Начну с того, зачем это нужно


Еще совсем недавно web был простым. Для успешной работы необходимо было знать html, css и популярную на тот момент, библиотеку jquery. На этом знания фронтенд-программиста заканчивались, да и за программистов их особо не считали, так, верстальщики или веб-мастера. Но веб стремительно развивается, интерфейсы становятся все сложнее и сейчас для многих проектов, в которых нет HighLoad и микросервисов (а они в большинстве случаев и не нужны), клиентская часть становится сложнее, чем серверная, и время жизни кода на клиенте обычно меньше, чем на сервере.
Также появляется целая армия фреймворков, которые по сути делают одно и то же, но разными способами. И программисты выбирают свой стек: кто-то React, кто-то Vue и так далее.
Но наше веб-приложение живет долго, а фреймворки и UI-библиотеки меняются быстро. В итоге через пару лет мы получаем легаси, который хочется переписать, но это долго, а бизнес не готов за это платить приложение же работает.
Я думаю, многие программисты слышали про закон Иглсона: Ваш код, который вы не просматривали 6 или более месяцев, выглядит так, будто его написал кто-то другой.


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


Учитывая все вышесказанное, хотелось бы иметь не один большой монолит, который хочется переписать, а набор микросервисов (назовем их модули, каждый из которых максимально изолирован, чтобы при необходимости мы могли быстро его заменить или написать новый на другом стеке (если, конечно, это нужно). И тестировать только те модули, код которых менялся.
Чтобы решить все проблемы, я написал фреймворк, который легко позволяет делить приложение на модули, причем каждый модуль при необходимости может иметь свой стек (React, Vue, Angular, Webix . )


Что мы получили


Модули (микросервисы)


Любое веб-приложение можно разбить на модули (хедер, футер, окно с чатом, боковое меню и т.д..


Вот основные их типы:


  • Root-модуль главный модуль, один на все приложение. Отвечает за взаимодействие между модулями.
  • Page-модуль понятно из названия, модуль-страница.
  • Layout-модуль это тоже должно быть понятно, модуль-шаблон для страницы.
  • Global-модуль модуль который можно вызвать из любой страницы нашего приложения (например окно с чатом, или уведомления).
  • Embed-модуль модуль который встраивается в Page-модуль или в Global-модуль.
    Все модули устроены однотипно. Они просто встраиваются в DOM дерево. Если наш Page-модуль встраивается в Layout-модуль, то Layout-модуль должен иметь контейнер с id (<div id='content'></div>), а Page-модуль должен туда монтироваться. Все довольно просто.
    Также все модули динамически импортируются, клиент загружает файл с кодом модуля только тогда, когда это ему необходимо.
    В итоге мы получаем примерно такую структуру:
    |--project_name_dir|--src|--modules  |--Root      |--root.js      ...  |--Module1      |--module.js      ...  |--Module2      |--module.js      ...  ...
    

    Перед тем как все это заработает, необходимо описать config файл.

    Конфиг файл


    import Root from 'Root/module';export default {// роутинг с помощю history Api или hash.historyApi: false,// корневой путь для приложения ('/example/path/').rootPath: '/',// класс Root-модуля.rootModule: Root,// название модуля главной страницы.mainModule: 'main',// названия модуля страницы 404module404: 'notfound',// функция для динамического импорта модуля.// module - название модуля и название директории модуля.import: async (module) => await import(./modules/${module}/module),modules: {auth: {// Название модуля - названия директории, в которой находится файл с модулем.module: 'ExampleAuth',},// Ключ Page-модуля отвечает за название роута для этой страницы.main: {layout: 'ExampleLayoutWebix',module: 'ExampleWebix',embed: {// В этот модуль мы встраиваем ExampleEmbed-модуль.example: {module: 'ExampleEmbed',},},},notfound: {layout: 'ExampleLayoutWebix',module: 'ExampleError404',},// Глобальный модуль флаг global: true,globalwnd: {global: true,module: 'ExampleGlobalWnd',embed: {example: {module: 'ExampleEmbedGlobal',},},},globalnotification: {global: true,module: 'ExampleNotification',},},};
    

    Наш конфиг файл может иметь дополнительные поля, если это необходимо:

    main: {module: 'PageMain',layout: 'Layout',icon: icon,title: 'Главная Страница',inMenu: true,}
    

    Мы можем использовать разные модули для различных условий:

    main: {layout: window.innerWidth < 1000 ? 'Layout_1' : 'Layout_2' ,module: window.innerWidth < 1000 ? 'Module_1' : 'Module_2 ,embed: {example: {module: window.innerWidth < 1000 ? 'Embed_1' : 'Embed_2' ,},},},
    

    Теперь поговорим об устройстве модуля.


    Все модули, за исключением Root-модуля, наследуются от класса Onedeck.Module.
    Класс модуля имеет внутри реализацию паттерна [одиночка (Singleton)][simgleton] и [наблюдатель (Observer)][observer].
    То есть объект создается только 1 раз и может подписываться и публиковать события.
    Пример Модуля:



    import Onedeck from 'onedeck';import App from 'ExampleModule/App.vue';import Vue from 'vue';/*** Class ExampleModule* module use Vue*/export default class ExampleModule extends Onedeck.Module {// Хук жизненного цикла init.// Срабатывает при инициализации нашего модуляinit (path, state, queryParam) {console.log('init', this.constructor.name, path, state, queryParam);this.VueApp = new Vue(App);this.eventHandler();}// Обработчик событий для данного модуля.eventHandler () {this.$$on('onAuth', () => this.$$rout({  path: '/main/',  state: null,}));}// Хук жизненного цикла dispatcher.// Срабатывает при переходе на url, тут можно описать логику при переходе.dispatcher (path, state, queryParam) {console.log('dispatcher', this.constructor.name, path, state, queryParam);}// Хук жизненного цикла mounted.// Срабатывает когда модуль смонтирован в DOM дерево.mounted (module, layout) {console.log('mounted', this.constructor.name, module, layout);}// Хук жизненного цикла destroy.// Срабатывает когда нам нужно очистить DOM дерево от нашего модуляdestroy () {this.$$offAll()this.VueApp.$destroy();document.getElementById('root').innerHTML = '';}}
    

    Про хуки жизненного цикла модуля вы можете более подробно почитать в документации. Также вы можете почитать в документации про Root-модуль. Его код почти идентичен коду обычного модуля.


    Роутинг


    Как вы уже заметили, в конфиге мы можем легко переключить вид роутинга с помощью конфига:


    // роутинг с помощю history Api или hashhistoryApi: false,
    

    Каждый модуль имеет метод $$rout:


    import Module from 'Example/module';// Так как наш модуль реализует паттерн Одиночка (Singleton), мы получим текущий объект модуля.const module = new Module()module.$$rout({// Указываем путь, первый элемент пути - название модуляpath: '/module_name/item/1',// Данные, которые мы хотим передать по указанному пути:state: {id: 1, name: 'example'},})
    

    Далее path и state можно получить в хуках жизненного цикла init и dispatcher.


    Общение между модулями


    Общение модулей происходит через события. Каждый модуль может вызывать два типа событий:


    • события модуля с помощью метода $$emit;
    • глобальные события с помощью метода $$gemit;

    События модуля создает сам модуль с помощью методов $$on или $$onOnce. А глобальные события создаем Root-модуль также с помощью методов $$on или $$onOnce.


    Более подробно о событиях вы можете почитать в документации. Также там есть ссылка на github с простым примером приложения.


    Выводы


    Итак, вместо монолита мы получили набор независимых модулей. Каждый модуль внутри себя содержит мини-приложение, которое можно отдельно собрать и протестировать.


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


    При необходимости мы можем использовать различные фреймворки в одном приложении.


    Теперь нам не нужно переписывать все приложение, мы можем переработать только конкретные модули и можем даже переписать их на другом фреймворке.


    Так же мы можем разрабатывать модули заточенные под определенную платформу и в конфиге указывать какой модуль для какой платформы подгружать.


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


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

Источник: habr.com
К списку статей
Опубликовано: 11.09.2020 10:13:26
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Reactjs

Vuejs

Frontend

Frontend-разработка

Микросервисная архитектура

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru