Все материалы сюжета:
- Зачем нужен менеджер пакетов, или почему именно Bower
- Frontend - rак все поменялось за последние 15 лет
- Клиентский JavaScript тогда и теперь
Мы живем в удивительное время. На наших глазах рождаются, развиваются и транформируются во что-то иное не только технологии, но и целые профессии. Именно так случилось с системными администраторами, которые сейчас практически исчезли, уступив место DevOps-инженерам. С frontend-разработкой все наоборот: она сейчас переживает самый расцвет. Почему так?
В те времена, когда компьютеры были большими, а интернет очень маленьким, никто толком не знал, что же в этом загадочном интернете можно делать. Как ты наверняка помнишь, почти все сайты были очень простые: текст с информацией, пара ссылок на аналогичную страницу и всё. Браузеры тоже были очень простые, а зачастую даже чисто текстовые (например, консольные), поэтому и странички состояли из самых базовых тегов HTML, которые размечали структуру текстового документа. Глядя на все, что происходит сейчас, можно сказать, что именно тогда и был золотой век семантики и теги использовались действительно по прямому назначению. Впрочем, золотое детство интернета быстро прошло, появились первые большие сайты с повышенными требованиями к внешнему виду, а значит, и к верстке.
Поскольку единственным универсальным способом точного размещения элементов дизайна были таблицы, то настала эра табличной верстки. CSS тогда еще не рассматривался большинством как инструмент позиционирования элементов на странице, в основном из-за недостаточной поддержки соответствующих свойств в браузерах. Лучшее, на что мог рассчитывать CSS, — управление цветом, выравниванием и положением шрифта, и то для этого было множество атрибутов у тегов (о, славный bgcolor).
Как следствие, не было никаких «фронтенд-разработчиков», поскольку не было самого фронтенда. Были верстальщики, и были программисты. Программисты делали все крутые вещи, а верстальщики рыдали и ждали IE6, в котором будет поддерживаться столько крутых вещей, например полупрозрачность PNG! Наивные, да?
Началом рождения того фронтенда, который мы сейчас наблюдаем, было появление возможности асинхронных запросов через XHR. Все сайты захотели себе AJAX, чтобы быть крутыми, быстрыми и отзывчивыми, а верстальщики открыли для себя, что JavaScript можно не только писать в атрибут onclick
, но и вообще активно его использовать для оживления страниц. Поскольку программисты не хотели марать руки в «каком-то скриптовом языке для браузеров», делать всю работу пришлось верстальщикам. И, как это обычно и бывает, работы становилось только больше.
По мере роста производительности браузеров на клиент, то есть в браузер, который работает на машине пользователя, стали переносить многие паттерны из «большого» программирования. Появились первые MVC-фреймворки, которые управляли загружаемыми через AJAX-данными, правильно их отображали на странице и делали другие запросы по необходимости. Все это было еще не так активно, как сейчас, просто потому, что JavaScript-движки были медленные и норовили подвесить браузер от совершенно пустячных задач.
Рождение фронтенда
Примерно в этот период все и началось. Хотя верстальщикам и раньше приходилось «оживлять» собственные макеты, накладывая на них реальные данные через выдаваемые программистами вызовы методов, но с появлением динамики на клиенте стало ясно, что заниматься формированием HTML на сервере и последующим его изменением на клиенте должен один человек. Отчетливо выделились бэкенд, как некоторая обертка вокруг базы данных, скрывающая ее внутреннее устройство и реализующая некоторые методы получения данных («ручки» для фронтенда), и фронтенд, который занимался выдачей требуемого HTML по запросам пользователей. Примерно в это время и обозначились основные задачи фронтенда: агрегация, шаблонизация и кеширование.
Агрегация — это обработка данных, поступивших от бэкенда, в тот вид, который наиболее удобен для последующей шаблонизации. Например, если бэкенд выдает требуемые данные двумя отдельными методами, а тебе в итоге нужен один список на странице, бывает удобно заранее слить результаты двух методов, чтобы упростить шаблон. Или, например, если бэкенд не умеет сортировать в нужном тебе порядке или таких порядков сразу несколько, то на этап агрегации может лечь и задача самостоятельной сортировки полученных данных.
Шаблонизация — это создание результирующего HTML из полученных данных. В разных архитектурах шаблоны бывают разной степени сложности: от простейших шаблонов, прозрачно отображающих пришедшие из базы данных сущности, до сложных систем, включающих в себя значительный кусок бизнес-логики.
Кеширование — это запоминание полученного по конкретному запросу ответа, чтобы в дальнейшем избежать запросов к базе данных и последующей обработки. Кеширование — это не всегда задача фронтенда, часто ее перекладывают на HTTP-сервер, однако совсем избавиться от этой части не получится: все равно никто лучше фронтенда не знает, как именно надо кешировать какие разделы сайта. У тебя может лежать статический файлик, который можно закешировать на год, а рядом будет AJAX’овая ручка, которая выдает актуальный статус системы и которую можно дергать несколько раз в секунду, получая разный ответ. Обрати внимание, что кешировать можно как готовый HTML, так и ответ от бэкенда по каким-то популярным запросам.
Ну и конечно же, огромным толчком для развития фронтенд-разработки стало появление Node.js. Если говорить точнее, то само появление Node.js явилось следствием повышающегося значения JavaScript, о котором мы говорили раньше. Но кого волнуют такие тонкости? Фронтенд-разработчики захотели свой собственный движок на знакомом языке, и они получили его. А вместе с движком они получили кучу возможностей.
Если раньше JavaScript воспринимался всеми как маргинальный язык для браузеров, то теперь появилась возможность запускать его на серверной стороне. Внимательный читатель уже знает, к чему это привело. Конечно же! Работы стало еще больше. Фронтенд-разработчики начали самостоятельно «собирать» свои проекты, то есть приводить их из того вида, в котором удобно разрабатывать, в тот вид, в котором все должно показываться пользователю (минифицировать код, загружаемый на клиент, минимизировать картинки, компилировать шаблоны по необходимости и так далее). Подробнее про сборку проектов расскажем ниже, но важен сам факт — фронтенд-разработчики захотели делать все сами.
Разумеется, в больших компаниях по-прежнему есть бэкенд-разработчики, замороченные на производительности и обработке огромных массивов данных, но сейчас вполне возможно создать небольшой проект, который был бы полностью написан на JavaScript. Раньше за такую идею тебя бы засмеяли «настоящие программисты», а сейчас они по большей части грустят и ругаются на прототипную парадигму наследования.
Ну и конечно, не стоит забывать и про возможность использования одинаковых шаблонов на серверной стороне и на клиенте, поскольку производительность современных браузеров позволяет выполнять шаблонизацию на клиентской стороне.
Структура современного фронтенда
Современная клиентская часть может быть устроена очень по-разному, и, как правило, ее вид очень сильно зависит от требований конкретного сайта. В каких-то случаях идеальным вариантом будет single page application с большим количеством динамики на клиенте, в других же нужны лишь отдельные интерактивные элементы в обычной структуре сайта. Так или иначе большая или меньшая интерактивность ложится на клиентскую сторону, общая сложность создания сайта (фронтенд + клиент) обычно одинаковая. Цикл жизни запроса от пользователя обычно состоит из следующих этапов:
- Запрос приходит на HTTP-сервер. Там запрос уже может быть отклонен (а-та-та, кто лезет на неправильный порт) или перенаправлен на статический раздел (например, если запрашивают CSS или JS) или собственно в наше приложение.
- Приложение получает запрос с определенной метаинформацией и осуществляет роутинг, то есть решает, какой кусок кода (контроллер) должен обрабатывать подобные запросы. Например, пользователю без куки логина на этом этапе можно отправить форму авторизации.
- Контроллер получает запрос и смотрит, какие данные ему нужно получить, причем это может быть многоэтапный процесс, целые цепочки запросов по определенным условиям.
- Контроллер агрегирует полученные данные и отправляет их на шаблонизацию.
- Шаблонизатор шаблонизирует шаблоном и отдает пользователю полученный результат.
Заметь, что запросы к AJAX-ручкам за данными тоже проходят эти этапы, просто обычно у них нет шаблонизации (в случае если ответ от бэкенда можно выдать напрямую на клиент) или она сильно упрощена до фильтрации и сериализации данных.
Конечно же, в разных архитектурах эти этапы выглядят по-разному. Например, контроллер может быть статическим файлом, на который HTTP-сервер прозрачно перенаправляет запросы, а затем уже наше приложение выполняет все необходимые методы бэкенда, описанные в нем, и дергает соответствующий шаблон. В случае с Node.js все этапы после HTTP-сервера обычно представляют собой модули, то есть JavaScript-код, а получение данных сводится, как правило, к HTTP-запросам к бэкенду.
Собственно, в упоминавшиеся нами старые времена все эти этапы тоже присутствовали, просто всем, кроме написания шаблонов (а зачастую и ими тоже), занимались бэкенд-программисты. Сейчас же JavaScript может все (а если он чего-то не может, смотри пункт первый), поэтому и зона ответственности бывших верстальщиков сильно выросла. Говорят, что бэкенд-программистам тоже стало сложнее, какая-то Big Data и мапредьюсы, но мне кажется, это все отмазки, чтобы не делать свою работу, а перекладывать ее на нас, несчастных фронтендеров.