Frontend без JavaScript

Встретил интересное мнение забугорного программиста, и проникся, так как сам стараюсь минимизировать JS в проектах.


Перевод статьи Matt Reyer — A JavaScript-Free Frontend

Предисловие

Я разработал первую версию Slimvoice на базе Angular 1 с бэкэндом на Node.js и MongoDB в 2014 году (тогда все они были в моде). В 2015 году принял решение полностью изменить UI и переписал проект на React. Оглядываясь назад, я понимает, что — это было неудачным решением.

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

В статье я рассказываю о решениях, которые принял в отношении веб-интерфейса, и делюсь некоторыми приемами UI без JavaScript, которые выработал на своём пути.

Single Page Apps

Кризис избыточного веса веб-сайтов, в целом, не идёт на поправку. Я устал от медленной загрузки сайтов, которые при этом не очень надежны. Кто-нибудь в последнее время пытался изменить описание карточки в Asana? Это чертовски медленная работа приложения… UI тормозит без веской причины, когда вы просто печатаете.

Во-первых, я живу в сельской местности, где скорость соединения с Интернетом составляет всего 2 Мбит/с. Загрузка «горячего» кэша Asana занимает 14 секунд . Во-вторых, приложение состоит из более чем 10 МБ несжатого JavaScript (изображено на рисунке внизу). Это огромный размер для исполняющего кода! Это вообще нормально?

Размер загружаемого JS кода

С Progressive Web App среднего уровня сложности вам нужна целая команда разработчиков, чтобы оно нормально работало. Большую часть кода вы получаете только чтобы заработал frontend.

Шутки в сторону. Загрузка компонентов приложения в правильном порядке — определённая проблема, на решение которой мы добавляем еще больше программного обеспечения (см. Redux и его друзья).

Что если бы мы могли покончить со всем этим?

Чем больше у вас кода, тем вы менее гибкие. Это как тягучая смола. Библиотеки JavaScript постоянно растут, и я не думаю, что люди критически оценивают фактическую потребность в них. Люди часто измеряют JavaScript в килобайтах или мегабайтах, как будто это по умолчанию справедливая плата за пользование приложением. Но это не так. А ведь вы ещё должны дождаться, пока процессор проанализирует и выполнит весь этот код. Все это наслаивается друг на друга…

Хорошо, ближе к делу. Я обнаружил секрет развития frontend, которым поделюсь с вами. Мало кто знает об этом, так что не отвлекайтесь.

  • Ваш интерфейс не сломается, если вы не будете использовать JavaScript.
  • HTML не перестанет работать.
  • Меньше кода всегда лучше.

Привет Elm — ты очень крут!

Простой HTML и CSS

Для Slimvoice я хотел пойти вразрез с современной технологией JS и сделать приложение полностью серверным. Вы можете сказать:

«Но Мэт! Пользователь должен каждый раз перезагружать страницу при использовании приложения, а это происходит довольно медленно!»

На что я скажу

«Ха! А вот и нет…»

Все мои ресурсы сжаты и кэшированы, что оставляет для передачи только HTML. У меня нет загрузочных лоадеров. В конечном счете — моё приложение быстрее, чем многие PWA, которыми я пользуюсь.

Не верьте мне на слово, откройте Инструменты разработчика в браузере и сравните Slimvoice с популярными PWA. Ах да, и у меня нет обработчика исключений JavaScript при отладке в консоли. Либо страница загрузилась, либо нет.

JS код Slimvoice

Checkbox/Label

Конечно, есть некоторые взаимодействия, при которых перезагрузка страницы была бы неприемлемой. Вот мой любимый трюк, чтобы добавить интерактивность к статической HTML-странице. Я использовал это в Slimvoice для всех выпадающих, модальных и фильтрующих UI элементов, и всё это работает без JavaScript.

  • Создайте div, содержащий произвольный элемент, который вы хотели бы показать/скрыть:
  • Непосредственно над ним добавьте инпут:
<input type="checkbox" id="myToggle" style="display: none;">

это создаст невидимый checkbox в DOM

  • Какой бы DOM-узел вы не использовали в качестве переключателя, оберните его в:
<label for="myToggle"></label>

где атрибут for будет соответствоватьid checkbox

  • Используйте CSS, чтобы все это заработало:
#myToggledUI {
  display: none;
}
#myToggle:checked ~ #myToggledUI {
  display: block;
}

Этот CSS говорит, что элемент #myToggledUI непосредственно предшествующий отмеченному элементу #myToggle должен быть показан, иначе скрыт. Оператор вообще ~ очень крутой! Полный рабочий пример.

А вот модальное окно, созданное с label, div и checkbox. Кнопка «Отмена» — это еще один label для того же checkbox, поэтому нажатие на него — модальное окно закрывает.

За модальным окном находится серый фон (position: fixed;), который также является label для checkbox, поэтому нажатие за пределами модального окна закрывает его.

Нет React компонентов. Нет слушателей события клика. Только простой и чистый HTML.

Modal без JS

Я не делал этого в примере, но вы всегда можете добавить любые CSS переходы, которые вам нравятся. Здесь нет ReactCSSTransitionGroup.

Элементы details и summary

Теги details и summary используются редко, но во многих случаях вполне приемлемы. Я использовал их на странице благодарностей, чтобы показать/скрыть лицензии на различные части программного обеспечения с открытым исходным кодом, которое я использовал в Slimvoice.

Быстро. Легко. Нет JavaScript. Работает везде.

Жаль, что вы не можете контролировать их внешний вид, но я не думаю, что создание маленького треугольника раскрытия, соответствующего стандартам вашего бренда, стоит того, чтобы навязать пользователю несколько мегабайт JavaScript.

Формы и проверка входных данных

Многие поля ввода имеют встроенные функции проверки. Документация Mozilla является исчерпывающей.

  • Не забывайте об required атрибуте, который запрещает отправку формы до тех пор, пока не будет заполнено определенное поле
  • Поля ввода чисел имеют атрибуты min, max и step
  • Текстовые поля могут быть типа email или пользовательского pattern
  • Текстовые поля имеют атрибуты minlength и maxlength
  • :valid и :invalid CSS-селекторы позволяют улучшить UX
Подсвечивание полей без JS

Да прибудет чистота

Я действительно использовал некоторый JavaScript в новом Slimvoice, но только когда взаимодействие не могло быть воспроизведено любым другим способом. Например, я реализовал нечеткий поиск в списке клиентов, чтобы вы могли легко фильтровать клиентов. Взгляните на код.

Поиск на JS

Я решил, что очень важно, чтобы позиции счетов-фактур можно было сортировать с помощью перетаскивания, поэтому использовал Mithril для UI редактирования счетов. Это единственная JS-зависимость во всем проекте (и только на одной странице), и когда у меня будет время в будущем, я с удовольствием избавлюсь от неё.

В моём приложении так мало JavaScript, что даже если я его минифицирую — это не принесёт значительного прироста производительности. Взгляните на мой код.

Сортировка на JS

Будущее

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

  1. Почему у нас не может быть стандартного поискового элемента, который фильтрует список на стороне клиента (аналогично тому, как ng-repeat | filter: работает в Angular 1)?
  2. Разве стандартный HTML-элемент для сортировки с помощью перетаскивания не будет крут?
  3. Более продвинутая функциональность проверки, например, сравнение равенства двух разных полей формы.
  4. Способность выполнить вышеупомянутый трюк с модальным окном/checkbox без ощущения хака и написания странного CSS.

Почему настройки UI в спецификации HTML застоялись и переложили процесс создания пользовательских элементов на плечи JavaScript?

Я думаю, что иметь более надежный набор стандартных элементов UI гораздо важнее, чем WebVR, WebBluetooth или любой другой маразм, который разрабатывается в наши дни.

Заключение

Это работает? Безусловно! Полная перезагрузка самой большой страницы через Интернет составляет 230 КБ. Поскольку я всё кеширую и сжимаю, каждый последующий просмотр страницы составляет около 6 КБ; гораздо меньше, чем SPA, которые я видел с эквивалентной функциональностью. Slimvoice быстрый и маленький, но не идет на компромисс с UX. Пользователи до сих пор любят это. Убедитесь сами на https://slimvoice.co.

В моём коде нет нет ничего сложного. Я бы чувствовал себя комфортно, передавая свой код кому-то другому, ничего при этом не объясняя. Я не знаю никого, кто бы реально мог сказать такое о frontend, разработанном на React/Webpack.

Я программировал более десяти лет и шесть лет занимался разработкой веб-приложений. Эти годы доказали, что преимущества JavaScript и PWA не так уж велики, но их недостатки огромны и часто игнорируются. В обозримом будущем я полностью покончу с JavaScript как с основным языком.

  • Вам, вероятно, не нужно Progressive Web App. Серьезно оцените, нуждается ли ваше приложение в такой сложности. Руководитель или клиент может потребовать PWA, потому что это круто и популярно, и подкрепит потребность множеством сомнительных аргументов. Убедитесь, что его аргументы верны.
  • Хватит отслеживать людей. Не позволяйте другим компаниям делать это от вашего имени. Вы выживете без Google Analytics. Вы выживете без Intercom. Обслуживайте все с вашего собственного домена.
  • Не бойтесь. Вы можете разработать «всё» самостоятельно! Вам не нужны фреймворки!
  • Не следуйте за хайпом. Принимайте критические решения о том, почему один подход лучше другого, несмотря на то, что говорится на рекламных страницах или на то, что делают все остальные. Люди, продающие новые классные инструменты, обычно скрывают их недостатки. У всего есть цена.

Я очень доволен тем, как появилась эта версия Slimvoice, но, конечно, ищу способы снизить использование JavaScript до нуля. Я был бы рад ответить на любые вопросы о дизайне или опыте разработки.

И, конечно же, спасибо моей замечательной жене Ruth Reyer, которая помогла с UI и подтолкнула меня написать этот пост!