Javascript, как и митьки, никого не хочет победить

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

Начну, как полагается, с конца. Сергей своё исследование современной экосистемы Javascript завершает следующим пассажем — “Что с этим всем делать и как в этом всём жить — большой вопрос и тема для отдельного исследования”.

У меня как раз подобралась подходящая цитата в ответ.

“Видите ли, — проникновенно сказал Горбовский в мегафон, — боюсь, что здесь какое-то недоразумение. Товарищ Ламондуа предлагает вам решать. Но понимаете ли, решать, собственно, нечего. Всё уже решено.”

Всё уже давно решено — любой современный веб-продукт, ориентированный на конечного пользователя, строится на экосистеме Javascript. React/Flux давно уже стал индустриальным стандартом, а ES6 давно перестал какой-то экзотической новинкой.

Можно спорить с тем, насколько эти инструменты совершенны, предлагать близкие альтернативы, но никакого настоящего выбора сейчас нет. Разве что React в этой связке можно заменять на что-то типа Vue.js или Angular2, но всерьёз предлагать воздержаться от использования JS/ES6 в качестве основного языка разработки в наши дни сродни предложению воздержаться от дыхания в кислородной атмосфере.

“В итоге совершенно неудивительно, что более-менее приличные крупные проекты на серверном и/или клиентском JS редки, как золотые самородки”

Возможно, мой опыт уникален, но мне посчастливилось наблюдать (и, зачастую, инициировать) запуск в production не меньше пяти этих самых самородков. Например, первая версия https://www.lieferheld.de/ создавалась вообще до появления Реакта, наша команда писала свой собственный фреймворк на node.js + Backbone. И да, если в 2013 году это было довольно-таки революционно даже для Берлина (особенно node.js), то в последние два года эта связка стала таким мейнстримом, и сравнение с самородком мне всё-таки кажется некоторым преувеличением.

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

Не очень понимаю, в чём проблема с разными диалектами языка. ES6 сам по себе прекрасен, лично я использую его безо всяких добавок, но и у Typescript есть свои плюсы. Никто вас не заставляет использовать Babel, если вам не нужны новые функции языка, которые ещё не приземлились в стабильной версии. Babel и схожие инструменты не ограничивают вас, а добавляют возможностей, ничего не отнимая от того, что у вас уже есть. Вы можете писать на ES5, ES6, TS или closurescript. Или Jquery. Это ваш свободный выбор. И для любого выбранного диалекта вы наверняка найдёте кучу документации и примеров. Кстати, благодаря тому же Babel, перейти от Typescript к plain ES6 не составляет ни малейшего труда. Многие ли современные языки могут похвастаться подобной гибкостью?

…оценки внедрения новых фич даже (или правильно будет сказать — в особенности) по чётко сформулированным бизнесом требованиям промахиваются на порядки

Мой опыт говорит об обратном. На проектах холдинга Deliveryhero GmbH (Lieferheld, pizza.de, суммарный трафик несколько миллионов заказов в месяц) равно как и на нынешнем месте работы, мне повезло работать с несколькими командами JS разработчиков (прямо сейчас их четыре, например). Все наши проекты выходили и выходят в срок, более того, я помню случай, когда первая версия продукта вышла за две недели до утверждённого плана. Несколько раз фронт-энд часть проекта была готова задолго до того, как появилась рабочая версия API (что вполне логично на мой взгляд, так как современные инструменты JS разработки её ускоряют и упрощают, позволяя инженеру сфокусироваться исключительно на создании идеального интерфейса и продукта в целом, а не на распутывании клубка элементов dom и связывающих их событий).

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

Эти снисходительные инвективы в адрес Node.js меня оставили в полном недоумении. Node.js как инструмент (язык + экосистема) конкурирует не с прости господи PHP, а с Java/Go/Erlang/Python. Мой опыт показывает, что это вполне сформировавшийся и эффективный язык для написания высокопроизводительных HTTP API. Наличие нескольких, а не одной абстракций для асинхронных вызовов лично мне кажется достоинством, а не недостатком. Promises и async это две разные идеологии, а выбор, повторюсь, это прекрасно.

…Теперь, раз уже я разошёлся, позволю себе добавить ещё несколько слов о React.js и том, что является моим постоянным предметом интереса и повседневной задачей — миграцией веб-приложений на современную и производительную архитектуру, которую, за неимением лучшего слова, я назову SPA, single-page application.

On React.js

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

Я в своё время участвовал в разработке фреймворка на базе Backbone и пытался достичь той же простоты и мощи абстракций. И я аплодирую инженерам Facebook, потому что они сделали то, что не удалось многим веб-инженерам. Эта модель в особенности прекрасна, если вы используете Redux или похожий подход, который позволяет разделить компоненты на контролирующие (уникальные для приложения) и контролируемые (их, как правило, нужно и можно переиспользовать).

On SPA vs MVC

SPA это сложный (но не теряющий производительности, потому что speed is a UX feature) пользовательский интерфейс. Это анимации, изменения в реальном времени, привлекательный дизайн. Это Facebook, тот же Medium, где вы читаете этот текст, медиа-приложения типа Spotify

Лирическое отступление: у меня пять лет назад был заказчик, для которого я с небольшой командой строил конкурента Spotify на Backbone/jquery. Это было очень больно, очень. Как был бы я счастлив, разрабатывай бы его сегодня!

SPA подразумевает HTTP API (чаще push, чем pull). SPA подразумевает гибкую систему композиции вашего приложения, умный роутинг и быструю работу с данными (я могу написать отдельную статью о достоинствах unidirectional data flow. Но поверьте на слово, это гениальная идея.)

SPA эмм сложны. Проектировать приложение в этой парадигме и производительный API для него сложно. Использовать современный JS сложно. Писать хороший интерфейс сложно.

MVC это… Wordpress, Django, Symfony и туча фреймворков поменьше. Это шаблоны и контроллеры. Это, самое главное, request/response парадигма, где сервер — центр принятия решений. Это простые в использовании (но сложные при масштабировании) концепты типа ORM. Это, как правило, высокая скорость разработки несложных приложений, это крайне понятная любому программисту структура. MVC прост. Запрос, ответ, данные, страничка. Нажали на кнопку — опять запрос, и так далее.

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

Ниша MVC стремительно сужается. Даже админки на несколько таблиц, простой CRUD к вашей базе данных — и то сегодня ваш скромный администратор хотел бы видеть обновления в реальном времени, а не терзать кнопку F5.

У SPA-подхода есть и другие спонсоры, кроме специалистов по пользовательскому интерфейсу. Переход на API driven apps совпал с подъёмом микро-сервисной архитектуры. MVC не масштабируется, поверьте человеку, который мигрировал не один и не два больших монолита (кстати, среди них были монолиты на Python и Node.js, так как MVC подход не зависит от языка). Распиливание монолита на микро-сервисы, как правило, идёт рука об руку с переходом на SPA, так как последний позволяет выделить относительно легко отдельные компоненты, их data flows и перевести их на client + API, постепенно отключая монолит от прямого доступа к базы данных. Но это уже другая история.

Заключение?

Если вы хотите услышать о настоящих рисках современной веб-разработки, то они следующие:

  • Webpack это гениальный инструмент, ставший стандартом де-факто, но у него очень высокий порог входа. Альтернативы типа gulp гораздо проще в использовании, но предоставляют на порядок меньше возможностей.
  • Рендер на сервере в Реакте реализован так себе. Рендерить всё дерево компонент очень дорого. Единого простого стандарта не существует (я видел хорошие результаты с https://www.npmjs.com/package/webpack-isomorphic-tools). Кэширование HTML в SPA это нетривиальная задача в смысле дизайна системы.
  • Структурирование CSS это самый недооцениваемый по сложности этап архитектуры, который, как правило, убивает переиспользование компонент.
  • Code obese это настоящая проблема для производительности, NPM + webpack маскируют реальный объём файлов, нужных для базового приложения.

Ну и много других, на самом деле. Но вот вопрос использовать ли Javascript SPA+Node.js в современном веб-приложении запоздал лет на пять. Используйте, конечно. И всё у вас будет хорошо.