Избыточная вариативность во Front-end Stack: суть и причины

Меня зовут Александр Черненко, и я 5 лет занимаюсь Front-end-разработкой. Я Technical Lead в компании Nullgravity, и мне удалось вырастить уже более 15 разработчиков с уровня Junior до Middle и выше. Я управлял разными командами, иногда приходилось задействовать на пять фронтов одновременно на одном проекте; бывало, что консультировал только одного человека, который самостоятельно разрабатывал проект.

В этой статье я хочу поделиться своим взглядом на Front-end Stack и ответить на вопрос, почему во Front-end так много разных фреймворков и что способствует появлению новых. Также хочу выделить критерии, по которым лично я выбираю те или иные технологии в крупных проектах.

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

Постановка проблемы

Допустим, вы достаточно компетентны и умеете разрабатывать аккуратно и без code smells на JS или TS. Какой Front-end Stack по мере развития вашего приложения обеспечит надежность и хорошую производительность и при этом не сильно устареет с течением времени?

Казалось бы, лидирующие позиции давно уже захватили библиотека React и фреймворк Angular. Но их рейтинги могут стать шаткими в ближайшие годы, ведь на арену постоянно выходят конкуренты, такие как Svelte, Stencil и другие. Их авторы весьма амбициозно заявляют, что именно их инструменты лучше, быстрее, удобнее. А что, если их развитие подхватят крупные корпорации и они начнут по своим характеристикам догонять или даже выигрывать у старых добрых «реактов» и «ангуляров»?

Лично я считаю, что React и Angular не уйдут с топовых позиций, но, во-первых, это мое личное мнение, а во-вторых, при выборе стека я руководствуюсь определенными принципами, которые влияют на мои предпочтения во фронтовых движках в будущем.

Наша индустрия сегодня чрезвычайно динамична, и это неспроста. Есть технический бэкграунд, который является первопричиной постоянных изменений во всем: в браузерах, во фреймворках и библиотеках, в design patterns и многих других вещах.

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

В чем проявляется избыточная вариативность

Начинающим Front-end-разработчикам вообще трудно разобраться, какой инструментарий выбрать и чьим guidelines следовать. Что делать после того, как научился писать на JS? Учить Angular, React, Vue или, может, сразу Svelte?

Стажировка в хорошей компании не даст ответа на эти вопросы. Большинство компаний и обучающих фирм ориентированы на тот или иной набор инструментов. Направленность на Angular, React или тот же Vue складывается исторически и экономически. Она зависит от того, каких специалистов больше.

Мало кто захочет двигаться «в ширину» и тратить время на освоение всего доступного арсенала, если только это не корпорация с неограниченными бюджетами на research. Каждая компания оттачивает мастерство использования определенных инструментов. Наиболее выгодно, когда у вас в целом по компании схожий технический стек и вы можете легко переключать людей между проектами.

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

У Android-разработчиков проблема вариативности инструментов не так явно выражена. В качестве основной IDE используется Android Studio, а в плане архитектуры кода есть «мейнстримовый» подход — Clean Architecture, который уже полюбился Android-сообществу и устоялся в нем. Guidelines, code style, tools во многом рекомендуются компанией Google.

Схожая ситуация у iOS-developers. Есть экосистема, которую заботливо создала и поддерживает компания Apple. Для большинства случаев достаточно использовать родные модули Swift, не прибегая к модулям сторонних библиотек. А в плане архитектуры существует Clean Swift Xcode — наиболее популярная IDE.

В Back-end-технологиях тоже много устоявшихся стеков. Литература, написанная для Java-разработчиков, устаревает не так быстро, как для разработчиков в web. Самый используемый фреймворк — Java Spring. Этого уже достаточно, чтобы решить, чему обучаться на начальных этапах.

У .NET developers экосистему поддерживает .NET Foundation и сам Microsoft.

Front-end выглядит иначе, ведь у нас нет единой «верховной» частной корпорации (такого уровня, как Google, Apple, Oracle или Microsoft), которая централизованно управляла бы правилами разработки для всех. Наши приложения должны одинаково хорошо работать на всех популярных операционных системах и браузерах.

Мы работаем со стандартами некоммерческих организаций, такими как W3С, WHATWG, TC39 и другими. И здесь, с одной стороны, полная свобода действий, с другой — полный хаос. За создание наиболее «правильного» инструментария и архитектурных подходов ведут конкурентную борьбу как Google и Facebook, так и менее крупные компании.

Вариативность в стандартах для web-приложений и ее причины

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

Для начала давайте разберемся, в чем вообще суть веб-приложения.

Веб-приложение — клиент-серверное приложение, в котором клиент взаимодействует с сервером с помощью браузера, а за сервер отвечает веб-сервер (согласно Wikipedia).

Front-end — это все, что касается клиентской части, и эта клиентская часть может технически существовать в разных формах.

Основные формы — Multi-Page application (форма классических веб-сайтов, существовавшая изначально), Single-Page application, Server-Side Rendering Application и модный сейчас Progressive Web Application. Не исключено, что в ближайшем будущем появятся другие варианты.

Также важно понимать, что деплоить Front-end-часть веб-приложения можно тоже по-разному: это может быть классический монолит, JAMstack-архитектура либо так называемые micro frontends.

Из-за чего могут появиться другие формы существования и деплоя веб-приложений и что лежит в основе развития Front-end? На этот вопрос я попробую дать расширенный ответ. Начну с причин, которые относятся к низкому уровню, и в конце перейду к высокому.

Факторы развития Front-end Stack

Основными факторами, которые развивают Front-end Stack, являются следующие.

Развитие в протоколах прикладного уровня (application layer protocols)

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

Объемы и скорость потребляемого трафика в сети постоянно растут.

Особенно это касается передачи видео. На рынке медийного контента уже практически везде поддерживается формат 4K, и такие гиганты, как Netflix, YouTube и прочие регулярно решают проблемы трансляции видео в высоком качестве.

Уже существуют сервисы, которые позволяют играть в игры из Steam или, для PS, прямо из браузера, они транслируют сформированное на удаленной графической карте видео по сети. Пока эти сервисы не такие удобные, как игровые компьютеры, но, думаю, через несколько лет ситуация изменится.

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

Возьмем, к примеру, протокол транспортного уровня.

К сожалению, большинство браузеров сейчас умеют работать только с TCP и отчасти с UDP. Спецификации этих протоколов родом еще из 80-х годов.

Многие сетевые специалисты, в том числе Марк Ноттингем, пишут о том, что в TCP есть ряд проблем.

Для их решения разработали протокол прикладного уровня QUIC, но не поверх TCP, а поверх UDP.

Схема работы протокола QUIC на основе UDP (источник)

Пока еще не придумали, как по умолчанию (без включения со стороны пользователя) поддерживать UDP в браузере из-за проблем с безопасностью. Возможно, это произойдет в будущем.

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

Поверх слоя TCP браузеры сейчас умеют работать с 2 протоколами приложений — старым добрым HTTP/1.1 и многофункциональным HTTP/2, который с 2015 года поддерживают большинство вендоров; но, как по мне, он все еще находится на стадии активного освоения со стороны поставщиков инструментов для разработки.

Работа внутри HTTP/1.1 тоже постоянно расширяется за счет появления новых заголовков, поддерживаемых браузерами.

Когда появился HTTP/2, было много статей о том, что теперь не нужно прибегать к сборке application bundle в 1 файл и не нужно объединять картинки в sprites.

На практике же достичь этого результата не так просто, детальнее можете почитать почему.

Вторым важным преимуществом HTTP/2 стала возможность сразу отдавать браузеру необходимые assets благодаря Server Push. Опять же, для этого необходимо использовать ряд вспомогательных библиотек, которые разруливают в таком случае проблемы с кэшированием и другие нюансы.

Еще одной абстракцией прикладного уровня поверх TCP являются WebSockets.

Веб-сокеты, в отличие от HTTP, позволяют работать с двунаправленным потоком данных, что делает эту технологию совершенно уникальной. При этом WebSockets обязывают вас брать на себя решение ряда вопросов по поддержке стабильного соединения и передачи данных (решенные за вас автоматически в HTTP/1.1 и HTTP/2, так как там действует классическая синхронная модель «запрос — ответ»). Эти проблемы фактически оставлены на откуп разработчикам. Они, с одной стороны, дают свободу действий, с другой — плодят множество «велосипедов». Если не вдаваться в подробности, то по факту мы имеем ряд конкурирующих популярных библиотек типа Socket.IO или SockJS (которые нужно настраивать одновременно и в браузере, и на стороне сервера), и, естественно, каждая имеет свои плюсы и минусы.

Допустим, вам необходимо разработать веб-приложение с push-notifications в браузер. Какие технологии вы возьмете в 2019 году? WebSockets или HTTP/2 плюс SSE? Однозначного ответа нет. Подробнее о проблематике выбора можно почитать здесь.

Ответ на этот вопрос будет зависеть от специфики проекта, от того, какие еще платформы будет поддерживать ваш сервер, и от того, как вы будете решать на сервере проблемы балансирования и масштабирования.

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

Развитие возможностей браузеров

Новые протоколы расширяют возможности браузеров. Browser Api сейчас вообще разрастается сумасшедшими темпами. Уже никого не удивишь push-notifications или service workers.

Много обновлений выходят в контексте общей парадигмы Progressive Web Applications продвигаемой Google. Они запланировали внедрение ряда новых APIв будущем, которые еще сильнее расширят возможности браузеров. Из них меня больше всего впечатлил анонс «Native File System API», которая позволит считывать и редактировать файлы на ОС пользователя.

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

Из других интересных браузерных анонсов мне запомнились Task Scheduling API и экспериментальный проект CSS Houdini. Первый позволит разработчикам более явно контролировать и расставлять задачи JavaScript-движка по приоритету, второй дает возможность с помощью JS и вне MainThread описывать поведение своих произвольных CSS-правил.

Развитие форматов обмена данными

Хороший протокол данных еще не означает, что вы их эффективно используете и экономите трафик. И хотя в большинстве решений доминирует стандартный JSON + REST, существует много сложных приложений, для которых нужно индивидуально подбирать наиболее оптимальный формат представления данных.

Из самых модных и часто используемых можно отметить GraphQL от Facebook, gRPC + Protobuf от Google (в связке с HTTP/2, но с «костылями» на фронте).

Еще довольно популярным является формат JSON-RPC.

Эволюция языков программирования

Пока индустриальным стандартом остается ECMAScript. Существуют фреймворки с применением других языков, которые компилируются в ES, но итоговый код для браузеров все равно генерируется на ES.

Начиная с 2015 года ES очень активно развивается и дополняется. Фактически мы каждый год получаем обновления в ECMAScript от Ecma International Technical Committee 39. Самое свежее обновление — это ES-2019 (ES10), ну а на стадии черновика в комиссии находится редакция ES-2020.

Мультипарадигмальность

Для разработки на ECMAScript недостаточно какой-либо одной парадигмы, и это большая проблема. Даже в рамках фреймворка вы можете писать код, совмещая подходы из объектно-ориентированного, функционального или даже реактивного программирования. Сейчас уже встречаются Front-end-приложения, которые вообще разрабатываются как microfrontends и разделены на изолированные модули, которые не зависят друг от друга.

Требования к продукту

Появление новых Browser API позволяет создавать продукты с новыми возможностями, а это уже весомое конкурентное преимущество. Поэтому бизнес просит разработчиков внедрять все более сложные и оригинальные функции. С течением времени требования к продукту только растут.

Для сравнения: 15 лет назад для разработки клиентской части рядового веб-приложения, чтобы реализовывать лендинги, заполнять формочки, кидать товары в корзину и листать галереи со слайдерами, достаточно было знать верстку и немного jQuery.

На сегодняшний день уже никого не удивишь личными кабинетами со сложными графиками, которые обновляются в реальном времени.

Развитие фреймворков и библиотек

Во второй половине двухтысячных Single Page Application только начинали появляться. В большинстве своем за UI отвечали верстальщики, многие из них не знали толком JavaScript и довольствовались библиотекой jQuery (которую сейчас так ненавидят).

С конца 2010-х начали появляться достаточно сложные и многофункциональные веб-приложения, и многострочный спагетти-код, написанный с использованием jQuery, уже не справлялся с возложенными на него задачами.

А еще в 2009 году Райан Дал разработал Node.js. С развитием и популяризацией Node.js и его пакетного менеджера npm появился популярный и простой способ размещать свои «библиотечки» на JS и совмещать их.

Вот тут на арену стали выходить большие фреймворки с сопутствующей инфраструктурой по сборке, тестированию, отладке и т. д. Например, в 2010 году вышел Backbone.js на архитектуре Model-View-Presenter.

Популярные фреймворки и библиотеки для Front-end (источник)

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

Суть js-фреймворков

Но также мы видим, как продолжают появляться достаточно интересные и элегантные способы — такие, например, как библиотеки lit-html или hyper-html.

Давайте взглянем на описание относительно молодого движка для веб-приложений Svelte: Svelte is a new way to build web-applications. It’s a compiler that takes your declarative components and converts them into efficient JavaScript that surgically updates the DOM.

А еще есть Angular, React, Preact, Vue.js, Elm, Ember.js, Meteor, Mithril, Polymer, Aurelia и много других.

Так или иначе, на каком «велосипеде» вы поедете, решать только вам.

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

Кроме эффективной работы с DOM есть еще одна причина появления новых фреймворков. Это стремление универсализировать и унифицировать процесс разработки, максимально использовать код. Для компаний IT development и для бизнеса это означает экономию и удобство в поддержке.

Есть vendors, которые занимаются созданием кроссплатформенных и изоморфных продуктов. Это Angular Universal, React Native, Flutter и другие, но это уже является отдельной темой для разговора и касается не только Web Front-end.

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

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

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

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

По сей день вся суть фреймворков и библиотек для построения web-applications состоит в том, чтобы предложить эффективный и удобный способ для работы с DOM (Document Object Model), деревом в браузере.

Дело в том, что каждое обновление узла DOM является весомым с точки зрения производительности, но при этом управление такими обновлениями должно быть удобным и доступным разработчику.

Существует множество вариантов решения этой задачи.

Я считаю, что сейчас на рынке наибольшую популярность в этом плане обрели React и Angular с их движками Fiber и Ivy.

Основные драйверы развития Frond-end Stack

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

О чем важно помнить, выбирая Front-end Stack

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

У фронтендеров, да и у большинства разработчиков, огромною роль играет community.

Изучайте противоположные мнения в community, читайте тематические ресурсы, каналы в мессенджерах, посещайте конференции, различные meetups, да и просто общайтесь.

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

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

Если какой-то очередной новый фреймворк кажется вам интересным и нужны более глубокие знания, старайтесь придумать кейс для тестового проекта или завести свой pet project. Вот тут вы и почувствуете на себе все нюансы использования.

В таком формате я познакомился с Progressive Web Applications. В компании мы проводили research на внутреннем проекте, и одной из целей было получение практического опыта использования PWA. Мы тогда научились работать с service workers и узнали различные технические нюансы. К примеру, мы узнали, что, применяя service-workers для кэширования ajax-запросов, обязательно использовать только fetch, соответственно, невозможно кешировать данные для service-worker c помощью библиотек, под капотом которых используется старый браузерный метод XHR. Это может быть реальной проблемой, если вы используете готовые решения. Мы тогда использовали npm-пакеты для работы с firebase, у них под капотом был XHR. Правда, тогда нам повезло, так как для них уже была реализована своя библиотека для offline-кэширования. Также мы поняли, что настроить базовый конфиг PWA не составляет труда, а вот работа с настройкой кэширования для режима offline оказалась затратной.

Еще есть вариант, когда вы пробуете новые вещи на реальном проекте, но не всюду, а в определенных небольших кусочках функционала. В компании, где я работаю, наш базовый стек — это React и Typescript. Как только появились React Hooks в альфа-версии React, мы внедрили их на нескольких участках нашего проекта. Главное было сделать это изолированно от основной части кода — таким образом, чтобы в случае чего можно было откатить эти компоненты обратно до классов. Нам очень понравился этот новый API, да и сам паттерн добавления в компоненты React Hooks позволяет писать более понятный код. Уже через месяц после того, как мы их внедрили, они вошли в полноценный релиз React. Мы внедрили их полностью в тот проект, сейчас продолжаем активно их использовать и на других проектах и отдаем им предпочтение.

Если же у вас совсем нет времени на проведение экспериментов, вы можете ознакомиться с проектом RealWorld. Это множество копий Medium, реализованных на разных стеках. Вы можете ознакомиться со всеми исходниками и пощелкать демки.

Я всегда обязательно смотрю на поддержку Typescript и наличие хороших test-suites, test-renderers, test-runners для изучаемого фреймворка, так как для больших проектов важно иметь статическую типизацию и наличие unit-tests.

Из своей практики хочу сказать, что чем больше для вашего стека развита экосистема, чем больше существует дополнительных инструментов, тем быстрее и продуктивнее вы будете работать

Еще отталкивайтесь от того, к какой парадигме вы ближе, к OOP или FP, насколько вы любите реактивность, какую часть решения вы хотите оставить «на откуп» фреймворка, а какую вы хотите «кастомизировать» самостоятельно.

Выводы

Устоявшихся подходов во Front-end еще не существует, эксперименты с технологиями, движками и с оптимизацией производительности продолжаются на уровне js-движков, фреймворков, компаний и даже стандартов.

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

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

Если вы хотите использовать новейшие фреймворки-пионеры, потому что они позволяют более эффективно работать с DOM, проверьте их на тестовых проектах.

При выборе определенного фреймворка рассматривайте не только его, но и всю сопутствующую или отсутствующую (как в случае с новейшими фреймворками) экосистему: возможности добавления статической типизации (TypeScript / Flow) и наличие типизированных npm-пакетов, testing tools, performance profiling tools и др.

Фреймворки ничто, мастерство все :)

Пишите код чисто. И да пребудет с вами сила!

Похожие статьи:
В выпуске: параллельные вычисления на одном ядре, поиск ошибки производительности, анонс ASP.NET Core RC2, 6 примеров неправильного...
Компания Prestigio объявила о выпуске компактного и доступного видеорегистратора с 1,5-дюймовым LCD-дисплеем - RoadRunner 130. Его камера с...
Компания Microsoft опубликовала итоги своего третьего квартала текущего года. В целом инвесторы и рынок оценили результаты его...
Олексій Зайченко — QA Lead у Daxx та співорганізатор в освітньому проекті Be QA Today. За 5 років він пройшов шлях від...
Самое время доказать, насколько хорошо ты разбираешься в браузерах, и порадовать себя к Новому году, ведь у нас...
Яндекс.Метрика