Frontend на пальцах: основы

Frontend — штука сложная. Тем, каким мы его все знали, мы его, наверное, уже не увидим. jQuery многие уже отправили на помойку. Я не столь радикален и следую принципу “для всего свои инструменты”. Маленький проект — подойдёт и jQuery. Но если вам предстоит долгая работа над большим проектом с большой командой, то посмотреть на новые технологии определённо стоит. Но сдвинуться с мёртвой точки не так-то просто. Я бы хотел помочь начинающим в этом непростом деле. Сегодня рассмотрим основы основ: принципы заложенные в основу разработки современного frontend’а.

В традиционном frontend’е у нас есть папка (назовём её public) в которой лежат JS, CSS и т.д., т.е. статические файлы. На эту папку натравливается веб-сервер. И она является корнем сайта, т.е. все запрашиваемые пользователями файлы раздаются из этой папки. Также есть точка входа. Обычно это корень (/). Когда к нему обращаемся, нам выплёвывается HTML.

Ну так вот: пользователь обращается (шлёт HTTP-запрос) к корню. Получает HTML. После загрузки HTML в браузер, начинается загрузка статики, указанной внутри HTML: JS, CSS и пр.

Это работает когда статические файлы пишутся нами собственноручно. Т.е.: написали JS — положили в public. Но это не работает с React и прочими современными инструментами.

Почему так нельзя в частности с React? — Приложения, которые пишутся на React, содержат не голый JS, а всякие очень специфичные для React вещи (дальше увидите сами), которые если и попадут в браузер, то просто не выполнятся и будут сыпаться ошибки. Решения есть два: не использовать эти специфичные вещи и писать на голом и чистом JS (с потерей удобства, разумеется), либо всё же использовать, но то что вы пишите, “превращать” в голый девственный JS, и уже после “превращения” складывать в public. Это самое “превращение” называется транспиляцией.

Из всего этого следует:

  1. JS-исходники должны лежать не в public. Обычно их кладут в папку src (её создают рядом с public).
  2. У нас должен быть транспилятор, который возьмёт наш код и превратит его в обычный JS.
  3. У нас должен быть инструмент, который будет запускать транспилятор. Он может это делать как по нашей команде, так и при каждом изменении в файлах. Так же этот инструмент будет заниматься перемещением “превращённого” JS-кода в нашу папку public. Такие инструменты называют сборщиками, либо бандлерами (bundler).
  4. У нас должна быть точка входа, осведомлённая о том, куда именно внутри папки public транспилятор положил файлы.

Точкой входа может являться простой index.html, лежащий в public, который отдаётся при обращении к /, и в котором жёстко руками написано по какому пути лежит транспилированный JS-код (<script src="..."></script>). Но тогда нужно настроить транспилятор так, чтобы путь и имя файла никогда не менялись (что не очень пригодно для продакшена).

Второй вариант: запрос к точке входа не просто отдаёт статичный HTML-файл, а обрабатывается каким-либо сервером и уже сервер генерирует HTML. Это означает, что на этапе генерации мы имеем возможность подставить путь до файлов с JS-кодом, созданных бандлером, в генерируемую страницу. Если пути постоянно меняются, то как же сервер должен узнать что именно подставлять? — Наш бандлер после транспиляции создаёт где-нибудь в папке, доступной серверу, файл, в котором в виде пар “ключ-значение” описано, какой из написанных нами файлов (я сейчас про те, что мы должны класть в src), по какому пути внутри public оказался. Ну разумеется нам остаётся лишь написать чуть-чуть кода, в котором мы опишем как этот файл парсить, и как, используя данные из него, генерировать HTML-код, выдаваемый пользователю по запросу. Тут уж на свой вкус. Можно это сделать на любом языке, который применяется для написания бекенда: Python, PHP, Ruby и т.д. Но я рекомендую Node.js. А вот почему:

  1. Наш транспилятор — это программа поставляемая в виде пакета-модуля для Node.js. Называется он Babel.
  2. Наш бандлер — это программа поставляемая в виде пакета-модуля для Node.js. Называется он Webpack.

Т.е. попросту говоря, нам нет смысла тащить ещё один инструмент/язык в проект.

Есть и третий вариант: пусть точкой входа является статичный index.html, но такой который не мы будем писать, а который будет генерировать для нас бандлер. На мой взягляд, этот вариант самый лучший. Но он подходит не всегда. В отличие от второго варианта, не нужно на каждый запрос генерировать страницу. Нам хватит обычного веб-сервера, который умеет раздавать статику (nginx, например).

Как вы видите, есть варианты при которых можно избежать написания серверной части. Но что делать, если приложение многостраничное и в нём не одна точка входа (/)? — В таком случае веб-сервер (тот же nginx), заставляют по всем запрашиваемым адресам (за исключением адресов статических файлов) отдавать index.html. А вот уже с помощью JS в браузере у пользователя вылавливают URL-адрес и в соответствии с тем, что в нём написано, строят/отрисовывают страницу. Но если пользователь ходит по ссылкам на странице, то делают следующее: с помощью JS запрещают любые переходы по ссылкам, отслеживают клики по ним и при клике производится подмена URL-адреса и вместе с тем перерисовка содержимого страницы. Обычно такой подход называют Single Page Application (SPA).

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

Поделиться Комментарии