Иногда, начиная новый проект, фронтенд-разработчик сталкивается с непонимаем со стороны команды, зачем нужно тащить на клиент какой-то фрэймворк. Это всё круто, конечно, но зачем нам пробовать что-то новое, если у нас есть jQuery!?
Да, у нас есть уйма js-фрэймворков и список на todomvc.com постоянно пополняется, да, для многих из них совершенно не обязательно городить полноценное MVC на клиенте, но почему-то для каждого нового проекта всегда милее взять хорошо знакомый jQuery и начинать по новой изобретать велосипед, чтобы хоть как-то не потонуть в нескончаемом потоке абсолютно неструктурированного js-кода.
Да, это здорово, когда фронтенд-разработчик знает о существовании js-паттернов и умеет их применять, но возникает вопрос: “Зачем каждый раз писать одно и то же заново и с появлением каждого нового человека в команде объяснять в чём сакральный смысл созданной архитектуры?” Ведь можно просто выбрать что-то готовое и тратить время на решение бизнес-задач. Да, готовое решение подходит не всегда. Но чаще всего ваш случай не такой уж уникальный.
Я взяла для примера задачу, которую часто приходится решать при написании стандартного веб-приложения: валидация формы на клиенте и отправка данных на сервер. Как-то так выглядел бы код на jQuery:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
Какие сразу возникают проблемы?
Если вы захотите, к примеру, порефакторить код (ведь это не последняя форма в вашем проекте) и вынести обработку сабмита в другой js-файл, а функция validate всё ещё уникальная для каждой формы, придётся создавать отдельный модуль для каждой формы, свою область видимости. Кто знает сколько таких функций validate у вас уже в проекте?
Вам придётся придумавать свои правила написания нового кода: все селекторы определяются там-то, новый модуль должен выглядеть так-то, а все обработчики событий пишем здесь. Вам нужно будет всё это придумать, описать, понять что вы что-то забыли, описать ещё немного. И каждый раз новому члену команды нужно будет объяснять это, и шанс, что он уже знаком с вашими привилами, стремится к нулю.
Чуть-чуть поменяем структуру html и нам сразу надо идти в наш js и искать все места, где чудесным образом всё вдруг перестало работать.
Здесь мы прощаемся с той самой идеей разделения логики и внешнего представления, вы проверяете данные на валидность и тут же меняете DOM дерево. Single responsibility? Не, не слышали…
Вам нужно самим следить какой js файл подключить в каком шаблоне, если же у вас в конечном итоге весь js собирается в один файл, то вы всегда должны контролировать, существуют ли в DOM дереве элементы, с которыми вы работаете. Очень много логики в голове. Чем больше разработчиков на проекте, тем более хрупким всё это выглядит.
Каждый раз, когда пользователь что-то меняет на странице, вы должны обновить данные в js-коде, и, наооборот, если вы меняете данные, не забудьте обновить внешний вид. И снова слишком много логики в голове.
Это самые распространённые проблемы, которые возникнут на большинстве стандартных проектов. И инструментов для их решения тоже уже написано не мало. Почти за любым крупным веб-проектом стоит написанный js-фреймворк.
Я попробовала решить ту же задачу валидации формы с помощью фреймворков, которые используют у себя Facebook и Twitter.
Twitter Flight
Twitter предлагает легковесный фрэймворк, который помогает структурировать код и избежать тех ошибок, которые часто допускают, при создании архитектуры в javascript. Он не диктует жёстких правил, вы можете использовать тот шаблонизатор, который любите, или не использовать его совсем. Вы можете посылать данные на сервер, так, как хотите и вам совсем не обязательно создавать большое количество структур, которые скорее всего в вашем приложении просто не нужны. Весь фрэймворк - это набор AMD модулей, выбирайте любой загрузчик и начинайте пользоваться.
Ваше приложение будет представлять из себя набор компонентов, причём каждый компонент отвечает либо за представление, либо за логику. В нашем примере мы можем создать два компонента для конкретной формы (внешний вид + логика) и два, которые будут содержать общие методы для всех подобных форм.
Пример UI компонента:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
Все компоненты общаются с помощью событий, вы не можете вызвать код другого компонента снаружи. Поэтому наш Data компонент подписан на события UI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
|
Общие методы и свойства вынесены в отдельные модули, которые во фрэймворке назывют миксинами. В данном случае создано два миксина, для логики и представления. Возможно после небольшого jQuery файла такой код покажется излишним, но как только приложение начнёт расти: появится больше одной формы, пользователи внезапно захотят не только создавать, но и редактировать сущности, выгода окажется очевидной. Проблема в том, что когда нужно срочно добавить небольшую фичу, а у вас уже тонны js-кода, куда проще впилить пару костылей, чем переписывать всё на новый фреймворк.
React.js
Facebook предлагает немного иной подход. В React.js ваш код – опять же набор компонент, но тут придётся отказаться от привычного убеждения, что шаблоны в javascript – это плохо. Разработчики фрэймворка считают, что компонент это единое целое и всё, что с ним связано – внешний вид, данные, все события – должно находиться в одном месте. Так будет проще вносить изменения. Для простототы написания можно использовать JSX – javascript, расширенный XML синтаксисом. В результате компонент выглядит довольно компактно:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
|
Этот вариант гораздо более непривычен, придётся разобраться в JSX, но преимуществ тоже хватает, например, 2-way data binding и довольно высокая скорость рендеринга, по сравнению с тем же Angular.js. Кроме того, есть положительные отзывы от разработчиков реальных проектов, на которых фрйэмворк уже испытан. Например здесь.
В обоих примерах вам удастся свести к минимуму проблемы, описанные в начале статьи. Конечно, вам придётся потратить какое-то количество времени на то, чтобы прочитать документацию и поискать примеры, но это время определённо окупится в будущем.
При написании web-приложения вы обязательно столкнётесь с рядом типичных проблем и рутинных задач. Вы всегда можете начать писать код с нуля или взять какой-то инструмент себе в помощь. Всё что вы выиграете во втором случае - ваше личное время. Просто перед тем, как сделать выбор, задайте себе вопрос: “Чем мой проект настолько уникален, что я не смогу использовать js-фреймворк, решающий часть моих проблем?”. У каждого из уже написанных инструментов свои преимущества и недостатки, но я не вижу причин, чтобы не попробовать найти что-то подходящее для себя.
Опять же, не стоит впадать в крайности, и я готова подписаться под каждым словом в этой статье. Что бы вы ни использовали при написании кода, всегда надо понимать, что ты делаешь.
P.S. Исходный код примеров можно посмотреть тут