JavaScript с момента своего появления проделал немалый путь от простых веб-страниц до полноценных приложений и даже серверов. Однако, чем сложнее становятся наши приложения, тем более остро встает вопрос подходящей для них архитектуры.

Вместе с Виктором gritzko Грищенко, создателем swarm.js (https://twitter.com/gritzko), рассмотрим современные подходы к построению архитектуры JS приложений как на сервере, так и на клиенте.

– Когда мы говорим о монолитных Web-приложениях, обычно имеется в виду архитектура, ставшая уже классической. Так называемый слоистый монолит хорошо прижился во многих корпоративных решениях. Расскажите, с какими недостатками данной архитектуры вам приходилось бороться в реальных проектах?

– С такой классической архитектурой я впервые столкнулся ещё в 2000 году в Банке России. Причём возникла она сама собой, в процессе аврального внедрения. Получился вполне обычный enterprise Java кошмарик, когда систему можно было запускать только целиком и только на сервере, с полной БД. Что-то сделать с получившимся монолитом было уже трудно, всё зависело от всего. Позже я видел такие же факапы в Яндексе. Это неизбежный этап, если приложение перерастает свою архитектуру.

– Как понять, что монолитный проект пора разделять на сервисы? Существуют характерные признаки?

– «Пора разделять» – это из серии «пора ампутировать». Разделение большой задачи на маленькие ортогональные подзадачки нужно осуществлять на этапе проектирования.

– Node.js очень активно развивается, статьи и руководства быстро устаревают. Существуют ли хорошие практики, на которые стоит равняться сегодня? Возможно, есть эталонные решения для построения микросервисной архитектуры?

Мне лично кажется, что микросервисы на основе REST – это те же миньоны, только в профиль. Так или иначе нужна асинхронная связь между подсистемами. В классике – это очереди сообщений, их используют везде и всегда везде использовали. Сейчас есть трендовые штучки – Kafka, Akka.

– Для монолитного приложения обычно достаточно иметь балансировщик нагрузки и нужное количество копий. Но в случае с микросервисами нужно также понимать, какой компонент системы следует масштабировать.

– Балансировщик как таковой решает проблему только для очень простых, в идеале stateless-приложений. Иначе начинаются проблемы синхронизации и конкурентного доступа к данным, в подвале открывается портал и из него лезут демоны. А компонент с одной понятной функцией однозначно проще масштабировать. Специализация и экономия масштаба – это вторая половина XVIII века, Адам Смит.

В общем-то, доклад не про микросервисы. Я прикладываю идеи «иммутабельной инфраструктуры» непосредственно к фронтенду, к тому, что работает в браузере.

– Хорошо, давайте обсудим код на клиенте. Какие проблемы сейчас актуальны?

– Например, при использовании модных фреймворков характерный размер клиентского бандла – это уже мегабайты JavaScript. Неприятненько, особенно на телефоне. Процесс сборки фронта – это уже целое большое дело.

Вытаскивание данных на клиента идёт полным ходом – сначала вытащили код, появились SPA, теперь постепенно вытаскиваем данные, хотим offline-first, быстрое время отклика и прочие плюшки.

В то же время, когда начинаешь говорить, что UI-компоненты должны быть чистыми функциями, это не считается странным. То есть, народ готов.

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

– Моя затея в том, чтобы строго разделить всё происходящее на фронтенде на (А) данные и (Б) всё остальное (компоненты, код). Причём, всё, что не данные – то функции. А функции – тоже данные, если подумать. Когда мы кладём код в систему контроля версий, он становится данными. То есть, у нас есть версионированные данные и версионированные функции, которые мы доставляем на клиент одинаково, одинаково кешируем и обновляем.

– А если чуть подробнее?

– Поясню на примере. Мы отправляем пользователю страницу, на ней сто кнопок. Мы не кладём код для ста кнопок в один большой бандл и не скачиваем всю базу данных, а отправляем только то, что нужно для рендера – часть данных и часть компонентов. Если пользователь начинает везде тыкаться – мы подтягиваем больше данных, больше компонентов. При этом то, что уже доставлено на клиента, кешируется навсегда. По необходимости обновляется.

Это похоже на микросервисы отчасти – этакое распиливание массы кода на иммутабельные/версионированные компоненты. Кстати, я лично предпочитаю всё-таки называть это версионированием, а не иммутабельностью. Версия, хоть данных, хоть кода, по определению иммутабельна, и фокус именно в этом.

В конечном счёте фундаментальная проблема здесь одна – и код, и данные должны работать на множестве устройств одновременно. Мы строим распределенные системы просто потому, что процессоры уже везде. Телефон – компьютер, книга – компьютер, телевизор – компьютер. Клиент-серверное мышление уйдёт в прошлое так же, как мейнфреймы ушли. А что придёт на смену – интересный вопрос.

– Звучит интересно, но как это совместимо с существующими библиотеками и фреймворками? Даже для частичной работы приложения потребуются большие основные зависимости (AngularJS, jQuery, ...).

– Ну, preact уложились в 3KB как-то.
Angular применять в таком контексте действительно незачем.

– Данная концепция уже сформировалась в отдельный проект? Где можно узнать подробности?

– Укладывается. Сейчас это скорее эксперименты. К декабрю расскажу, что получилось.




Кроме доклада Виктора на конференции HolyJS (11 декабря, Москва, Radisson «Славянская»), рекомендуем обратить внимание на следующие доклады:

Поделиться с друзьями
-->

Комментарии (4)


  1. SergeyEgorov
    21.10.2016 15:05

    Читая заголовок мне и в голову не пришло что это фактически тизер конференции HolyJS…


  1. rodial
    21.10.2016 15:08
    +4

    Описанная идея очень интересная, ещё хотелось бы увидеть нормальную реализацию — тогда может взлететь.
    А за наводку на preact огромное спасибо.


    1. max1gu
      23.10.2016 00:42
      +1

      1С — там всю жизнь так было: код качается с сервера из базы.


  1. overmes
    21.10.2016 18:57
    +4

    Очень похоже на то как работает requirejs из коробки.
    Так раньше часто проекты работали, потом начали все сжимать в один файл, теперь снова начали делить :)