Около десяти лет назад сообщество веб-разработчиков впервые начало обсуждать концепцию "Single-Page Application" и искать способы ее реализации. К тому моменту разработка графических интерфейсов уже не являлась чем-то новым и поэтому многие вещи заимствовались у существующих решений и немного адаптировались под специфику браузеров. Наиболее успешным результатом подобной работы оказался Backbone.js — объектно-ориентированный MVC-фреймворк, который в свое время использовался в BitBucket, Basecamp, Stripe, Airbnb и Trello. Со временем он был полностью вытеснен следующим поколением фреймворков, но... Что если бы этого не случилось? Как бы тогда выглядела современная разработка веб-интерфейсов?  Для начала давайте переместимся назад во времени и посмотрим на то, как именно раньше осуществлялась разработка SPA. Сначала наши "компоненты" описывалась с помощью текстовых шаблонов:  Такие шаблоны могли быть реализованы в виде обычных JavaScript-строк, но этот подход не пользовался особой популярностью из-за сложности работы с многострочным текстом (template strings на тот момент не существовало).  Затем эти шаблоны использовались в самих "компонентах", которые здесь и далее мы будем называть View:  Для обработки пользовательского ввода указывался CSS-селектор источника события, название прослушиваемого события и название (sic!) функции-обработчика: Чтобы отреагировать на изменение отображаемых данных следовало подписаться на соответствующее событие модели и указать функцию-обработчик: Обратите внимание, здесь используется "ленивый" обработчик события — любое изменение данных приводит к полному пересозданию элементов. Лучшей практикой считается прослушивание изменения конкретного атрибута модели и ручное обновление его отображения в DOM: Безусловно, Backbone не был идеальным решением и его использование всегда было связано с проблемами и трудностями, причинами которых были: 1. Пробелы в архитектуре На самом деле Backbone был не полноценным самостоятельным решением, а скорее фреймворком для создания других фреймворков. К примеру, в нем полностью отсутствовали контроллеры (С из MVC, посредник между данными и их отображением), отсутствовала стандартная реализация функции "View.render()", в нем не было стандартных способов отображения списков данных и вложения одних View внутрь других. Необходимость самостоятельного поиска решений для всех вышеперечисленных задач серьезно затрудняла использование фреймворка рядовыми специалистами и приводило к тому, что каждое приложение на Backbone разрабатывалось в своем собственном уникальном стиле. 2. Внешние зависимости Для использования Backbone требовалось подключение трех сторонних библиотек: Это существенно увеличивало размер приложения и ставило фреймворк в сильную зависимость от сторонних проектов. 3. Developer Experience (?) Главным преимуществом следующего поколения фреймворков являлось существенное упрощение и ускорение процесса разработки. Как уже было продемонстрировано выше, обновление данных во View ранее требовало написания большого количества кода, а в новой реактивной модели разработки в этом не было никакой необходимости — достаточно было единожды описать что и где должно отображаться, а все дальнейшие обновления происходили автоматически. Но это преимущество совсем не так однозначно если мы посмотрим на ситуацию с точки зрения конечного пользователя. Дело в том, что эти автоматические обновления даются нам не бесплатно — они увеличивают потребление RAM (хранение VDOM) и CPU (процедура сравнения VDOM), что в конечном итоге приводит к замедлению реакции интерфейса и увеличению расхода батареи мобильных устройств. Так что в данном случае мы имеем некоторое противоречие: с одной стороны разработка ускоряется и удешевляется, но с другой — качество конечного продукта ухудшается.  Стоит коротко упомянуть и те вещи, которые изначально были сделаны правильно: 1. Архитектура  Разработчикам навязывалось использование лучших практик, они вынуждены были соблюдать принцип разграничения ответственности и использовать событийную модель взаимодействия.  2. Минимальная абстракция  Разработчики имели прямой доступ к DOM, что позволяло использовать любые нативные библиотеки (слайдеры, попапы и т.п.) без применения специфичных для фреймворка оберток. 3. Кодовая база  Исходный код фреймворка был предельно прост и краток, в нем можно было полностью разобраться буквально за пару вечеров.  4. Нативность  Фреймворк не расширял стандарты платформы (HTML, CSS, JS) и не изобретал новых, вследствие чего его использование не требовало ни модификации инструментов разработки, ни добавления дополнительных шагов сборки. 5. Использование ООП  Да, оно имеет спорную репутацию, но ООП отлично ложится на специфику разработки GUI, где оно давно и успешно применяется (Qt, GTK, да и сам DOM), и тем более оно более актуально в контексте JavaScript, в котором нет ни иммутабельности, ни структур данных, не требующих полного перевыделения памяти при каждом изменении. Несмотря на то, что многое из вышесказанного выглядит достаточно неудобным и атавистичным, но в основе всего этого лежат достаточно неплохие идеи. Может ли быть так, что дальнейшая эволюция этих идей могла бы составить существенную конкуренцию новым возникающим фреймворкам?  Чтобы проверить эту гипотезу мы создадим функциональный прототип этакого "Backbone 2.0", и начнем мы с того, что сформулируем требования к нему. Чего бы мы хотели и ожидали от фреймворка в 2021-м году? Ответ на этот вопрос уже дан выше: 1. Полноценной реализации архитектуры и всех ключевых функций Решение должно справляться со своей основной задачей сразу же из коробки. Кастомизация должна быть возможна, но не должна препятствовать быстрому началу работы. 2. Отсутствия внешних зависимостей Нужны ли нам сейчас jQuery, Underscore и шаблонизаторы? Нет: 3. Адекватного Developer Experience Выше мы уже определили, что DX несколько конфликтует с UX, и наша задача — сделать так, чтобы разработчики могли самостоятельно решать что из этого им важнее. Нам следует предоставить возможность выбора: Да, ничто не мешает нам подключить и использовать другой рендерер внутри View. В этом и заключается одна из прелестей Backbone и MVC — они определяют области ответственности и их интерфейсы, но не навязывают их реализацию.  Ну и если мы говорим про DX вообще, то обеспечить его мы можем предоставив продуманный API, обширную документацию (API, комментарии к коду, обучающие материалы) и используя в разработке более современные технологии и подходы, где нам сильно мог бы помочь TypeScript с его более полноценной реализацией ООП и относительной типобезопасностью. NB: Использование TypeScript хоть и противоречит нативности, но его использование решает намного больше проблем, чем создает.   Итак, берем Backbone, выкидываем из него сомнительное и неудачное, заполняем возникшие и уже присутствовавшие пробелы, выполняем глобальный рефакторинг и… получаем Old Skull Framework. Для создания View теперь достаточно просто указать HTML и описать логику обновления. Больше никакой головной боли с шаблонизаторами и ручным инстанцированием элементов: Взаимодействие между данными и их отображением теперь единообразно регулируется с помощью Presenter: Вложение одного View внутрь другого больше не является проблемой: В аналогичном стиле реализовано и всё остальное: Итоговый размер получившегося фреймворка удивляет и даже заставляет усомниться в корректности замеров: И самое интересное — это производительность. Результаты js-framework-benchmark показывают, что Old Skull существенно обгоняет по производительности как Angular, так и React: Длительность (мс):  Метрики запуска:  Выделение памяти (Мбайт):  NB: Скриншоты сделаны 12-го октября 2021-го года с официальных результатов  В результате мы видим, что развитие идей, заложенных в Backbone.js, действительно приводит нас к ощутимо более доступным и отзывчивым веб-интерфейсам, которые к тому же реализуются таким образом, что разница между традиционными языками программирования и JavaScript сводится к минимуму. Что вы думаете обо всем этом? Имеют ли ООП и MVC место во фронтенд-разработке? Насколько DX важнее UX? И… не возникает ли у вас ощущение, что мир фронтенд-разработки где-то повернул не туда? Ссылки: Беззаботный безработный