Интересные трюки HTML. Экстремальный минимализм

в 9:00, , рубрики: css, html, NoPaste, ruvds_статьи, Textarea Cache, Total Blocking Time, Википедия, время загрузки, делегирование событий, оптимизация JS, оптимизация сайта, опциональные теги

Интересные трюки HTML. Экстремальный минимализм - 1


Мы уже много говорили про оптимизацию сайтов до минимального размера, преимущества статичного HTML, а также упаковку сайта (и веб-сервера) в портативный формат одного исполняемого файла, который нативно исполняется под любой ОС.

Но стремление к минимизации может пойти дальше, если вы хотите поместить весь сайт в адресную строку браузера. А с помощью сокращателя ссылок даже большой сайт сжимается до восьми байт. В этом случае и хостинг не нужен (то есть роль хостинга выполняет сервис сокращения ссылок).

▍ Сайт в URL

Вот концептуальный пример:

https://smolsite.zip/UEsDBAoAAAAAAEZkYVdE9j5DPAAAADwAAAAKAAAAaW5kZXguaHRtbDwhRE9DVFlQRSBIVE1MPjx0aXRsZT7S5fHyPC90aXRsZT48cD7P8Oji5fIg9+jy4PLl6//sINXg4fDgIVBLAQIfAAoAAAAAAEZkYVdE9j5DPAAAADwAAAAKACQAAAAAAAAAIAAAAAAAAABpbmRleC5odG1sCgAgAAAAAAABABgAd3HKkqYM2gF3ccqSpgzaAfnEyWumDNoBUEsFBgAAAAABAAEAXAAAAGQAAAAAAA==

Это делается очень просто: создаём статичный HTML-сайт из index.html и других файлов, архивируем всё в ZIP и кодируем в Base64:

$ zip -DXjq9 somesite.zip index.html mylogo.png
$ echo "https://smolsite.zip/`cat somesite.zip | base64 --wrap 0`"

И всё, потом полученный ZIP можно вставлять в адресную строку после https://smolsite.zip/ — и сайт откроется в браузере (на КДПВ). Согласно FAQ, сервер разархивирует его содержимое и хранит в памяти 15 минут, хотя теоретически извлечение контента из архива может сделать и сам браузер, так что нынешнее серверное решение не вполне оптимально.

Этот сайт можно ещё сильнее сжать с помощью сокращателя ссылок: https://tinyurl.com/4a7huvj2. В этом случае мы используем сервис сокращения ссылок в качестве бесплатного веб-хостинга.

Smolsite.zip — это часть проекта LWAN по созданию инфраструктуры для максимального производительного, эффективного и легковесного веб-сервера.

Точно также в качестве бесплатного веб-хостинга можно использовать QR-коды, распечатанные на бумаге. Такие сайты откроются в браузере даже в отсутствие интернета. Полностью офлайновый хостинг.

Такие же URL можно составлять по схеме Data URI, например:

data:text/html,<h1>My%20small%20website</h1><p>Look,%20it's%20real!</p>

Вставьте это в адресную строку — и у вас откроется «сайт». Можно использовать его как ">блокнотик для записей, если у вас нет отдельного notepad'а (например, на хромбуке).

Это чем-то напоминает сервис NoPaste, который тоже превращает произвольный текст в URL вроде такого. Аналогичные проекты itty.bitty.site и goog.space.

▍ Как восстановить текст из браузера

Если браузер по какой-то причине обновил страницу и текст в окне потерялся, можно воспользоваться этим советом: сделать дам памяти Firefox и поискать потерянный текст там. Инструкция работает для любых текстовых форм, в том числе для самодельных браузерных «блокнотиков» из предыдущего раздела.

Есть ещё расширение Textarea Cache (Chrome и Firefox), которое сохраняет в кэше текстовые данные из форм.

▍ NoJS и NoCSS

На Хабре упоминали клуб 1kB для сайтов размером меньше 1 КБ. Кроме него, есть и другие содружества минималистов: например, No JS для сайтов, которые не используют JavaScript, а также No CSS.

Наверное, такими темпами стоит ожидать в будущем появления клуба No HTML с веб-страницами в чистом тексте, без необязательных тегов, только необходимый минимум. На самом деле в HTML много опциональных тегов, которые необязательно использовать. Согласно официальной спецификации, тег <html> не является обязательным. Его можно удалить и в начале, и в конце документа.

Кроме того, во многих случаях можно безболезненно опустить теги <head> и <body> (в начале и в конце), а также закрывающие теги <li>, <dt>, <dd>, <p>, <rt>, <rp>, <optgroup>, <option>, <colgroup> (в начале и конце), <caption>, <thead>, <tbody> (в начале и конце), <tfoot>, <tr>, <td> и <th> (только внимательно прочитайте условия, при которых теги можно игнорировать). Это информация из официальной документации WHATWG по ссылке выше.

Например, такая таблица:

<table>
 <caption>37547 TEE Electric Powered Rail Car Train Functions (Abbreviated)</caption>
 <colgroup><col><col><col></colgroup>
 <thead>
  <tr>
   <th>Function</th>
   <th>Control Unit</th>
   <th>Central Station</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>Headlights</td>
   <td>✔</td>
   <td>✔</td>
  </tr>
  <tr>
   <td>Interior Lights</td>
   <td>✔</td>
   <td>✔</td>
  </tr>
  <tr>
   <td>Electric locomotive operating sounds</td>
   <td>✔</td>
   <td>✔</td>
  </tr>
  <tr>
   <td>Engineer's cab lighting</td>
   <td></td>
   <td>✔</td>
  </tr>
  <tr>
   <td>Station Announcements - Swiss</td>
   <td></td>
   <td>✔</td>
  </tr>
 </tbody>
</table>

И её полный аналог после удаления необязательных тегов:

<table>
 <caption>37547 TEE Electric Powered Rail Car Train Functions (Abbreviated)
 <colgroup><col><col><col>
 <thead>
  <tr> <th>Function                              <th>Control Unit     <th>Central Station
 <tbody>
  <tr> <td>Headlights                            <td>✔                <td>✔
  <tr> <td>Interior Lights                       <td>✔                <td>✔
  <tr> <td>Electric locomotive operating sounds  <td>✔                <td>✔
  <tr> <td>Engineer's cab lighting               <td>                 <td>✔
  <tr> <td>Station Announcements - Swiss         <td>                 <td>✔
</table>

Или взять стандартный шаблон документа:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Hello</title>
  </head>
  <body>
    <p>Welcome to this example.</p>
  </body>
</html>

Он полностью аналогичен следующему:

<!DOCTYPE HTML><title>Hello</title><p>Welcome to this example.

Если вспомнить, то оригинальная спецификация языка HTML от Тима Бернерса-Ли, опубликованная 29 октября 1991 года, содержала всего 18 тегов: <title>, <nextid>, <a>, <isindex>, <plaintext>, <listing>, <p>, <h1>…<h6>, <address>, <hp1>, <hp2>…, <dl>, <dt>, <dd>, <ul>, <li>,<menu> и <dir>. Недавно документу исполнилось 32 года. Говорят, что HTML был разработан под сильным влиянием универсального языка разметки SGML, оттуда вся его структура и логика.

▍ Оптимизация скриптов

В этом году инженеры Википедии рассказали, как они оптимизировали JS-скрипты, значительно ускорив загрузку страниц. Этот опыт может быть полезен и другим веб-разработчикам.

Оптимизация Википедии свелась к двум простым шагам:

  1. Удаление лишнего JavaScript. Нужно понимать, что JavaScript — основная причина медленной работы сайта. Так что просто вырезать скрипты — самый простой и быстрый способ ускорить его. Например, в мобильной версии Википедии профилирование показало, что основное время выполнения приходится на метод _enable, который отвечает за разворачивание/сворачивание контента.

    Интересные трюки HTML. Экстремальный минимализм - 2

    Внутри него больше всего времени уходит на вызов метода .on("click") jQuery. Если посмотреть код, то вызов .on("click") прикреплял прослушку событий почти к каждой ссылке на странице, чтобы открывался соответствующий раздел, если это внутренняя ссылка с хэшем.

    function _enable( $container, prefix, page, isClosed ) {
      ...
      // Restricted to links created by editors and thus outside our
      // control T166544 - don't do this for reference links - they will
      // be handled elsewhere
      var $link = $container.find("a:not(.reference a)");
      $link.on("click", function () {
        // the link might be an internal link with a hash.  if it is check
        // if we need to reveal any sections.
        if (
          $link.attr("href") !== undefined &&
          $link.attr("href").indexOf("#") > -1
        ) {
          checkHash();
        }
      });
      util.getWindow().on("hashchange", function () {
        checkHash();
      });
    }

    В длинных статьях Википедии тысячи ссылок, что и увеличивало время выполнения на 200+ мс на слабеньких устройствах.

    Этот факт не заметили раньше по двум причинам:

    • Задержка проявлялась только на очень больших страницах с большим количеством ссылок.
    • Веб-дизайнеры часто тестируют страницы на современных устройствах, игнорируя смартфоны пяти- или десятилетней давности. Хотя теми пользуется огромное число людей, и не только в странах третьего мира, но и в остальных. Миллиарды человек.

    Самое интересное, что этот фрагмент, по сути, вообще не нужен. Дальше в коде страницы уже была прослушка события hashchange. Поэтому метод checkHash вызывался дважды при нажатии на ссылку, так что предыдущий код является полностью избыточным. Оказалось, что его можно удалить полностью, сразу же резко сократив время загрузки мобильных страниц на сайте.

  2. Оптимизация существующего JavaScript. Дальнейшее профилирование выявило похожий метод initMediaViewer, который выполнялся около 100 мс. Он прикреплял прослушку событий к каждой уменьшенной картинке на странице, чтобы нажатие по ней выводило на экран полное изображение:
    /**
     * Event handler for clicking on an image thumbnail
     *
     * @param {jQuery.Event} ev
     * @ignore
     */
    function onClickImage(ev) {
      ev.preventDefault();
      routeThumbnail($(this).data("thumb"));
    }
     
    /**
     * Add routes to images and handle clicks
     *
     * @method
     * @ignore
     * @param {jQuery.Object} [$container] Optional container to search
     * within
     */
    function initMediaViewer($container) {
      currentPageHTMLParser
        .getThumbnails($container)
        .forEach(function (thumb) {
          thumb.$el.off().data("thumb", thumb).on("click", onClickImage);
        });
    }

    Аналогично предыдущему случаю, от этого страдают страницы с тысячами картинок, а задержка может составить сотни миллисекунд.

    Решением стало делегирование событий. Это мощная техника, позволяющая прикрепить обработчик событий не ко всем элементам, а только к одному общему предку. В нашем случае он прикрепляется к контейнеру, который содержит все картинки, а источник событий проверяется через свойство event.target в обработчике. Как вариант, можно использовать event.target.closest(selector) из API. Проверка показывает, откуда поступило нажатие: по уменьшенной копии или нет.

    Вот как выглядит новый код:

    /**
     * Event handler for clicking on an image thumbnail
     *
     * @param {MouseEvent} ev
     * @ignore
     */
    function onClickImage(ev) {
      var el = ev.target.closest(PageHTMLParser.THUMB_SELECTOR);
      if (!el) {
        return;
      }
     
      var thumb = currentPageHTMLParser.getThumbnail($(el));
      if (!thumb) {
        return;
      }
     
      ev.preventDefault();
      routeThumbnail(thumb);
    }
     
    /**
     * Add routes to images and handle clicks
     *
     * @method
     * @ignore
     * @param {HTMLElement} container Container to search within
     */
    function initMediaViewer(container) {
      container.addEventListener("click", onClickImage);
    }

До оптимизации время загрузки скриптов на мобильных устройствах нижнего уровня доходило до 600 мс, что неприемлемо долго для интерактивных интерфейсов. В такой ситуации страница блокируется: ни прокрутка, ни переход по ссылкам, ни нажатие кнопок не работают, что вызывает раздражение у посетителей. И нужно учитывать, что выполнение скриптов 600 мс — это только первый этап ожидания. Затем пользователь должен ещё дождаться выполнения соответствующей задачи обработчика кликов (click handler) и рендеринга страницы.

В результате оптимизации удалось снизить время выполнения скриптов вдвое, т. е. до 300 мс. Хотя это тоже долговато. По современным стандартам веб-разработки всё, что дольше 100 мс, считается «медленным» процессом, поскольку пользователь не считает такое взаимодействие мгновенным и нативным.

Разработчики Google ввели для измерения подобных «блокирующих» взаимодействий специальную метрику Total Blocking Time. Из-за фоновых задержек на простаивающие задачи реальный бюджет для обработки ввода не превышает 50 мс:

Интересные трюки HTML. Экстремальный минимализм - 3

По крайней мере, таковы рекомендации экспертов.

Синтетические тесты Википедии показали, что в результате оптимизаций время загрузки мобильной версии на телефоне Moto G (5) сократилось на 280 мс, из них примерно 200 мс принесла первая оптимизация с удалением кода. Конечно, это старенький бюджетный смартфон, но и на новых моделях ускорение загрузки мобильной Википедии в апреле-мае 2023 года тоже было заметно на глаз.

Интересные трюки HTML. Экстремальный минимализм - 4

После выпуска в продакшн мониторинг на реальных пользователях подтвердил эти изменения.

Для дальнейшей оптимизации TBT опытные специалисты рекомендуют разбивать большие задачи на ряд мелких.

Интересные трюки HTML. Экстремальный минимализм - 5

После разбиения задач на части у браузера больше возможностей реагировать на более приоритетную работу, в том числе и на взаимодействие с пользователем. Другими словами, время отклика может кардинально уменьшиться.

Интересные трюки HTML. Экстремальный минимализм - 6

Так или иначе, но этот пример ещё раз доказывает, что заметный результат приносят точечные, целевые воздействия. Иногда достаточно потратить пять-десять минут, посидеть, внимательно посмотреть профайлер и подумать. Этого достаточно, чтобы выполнить какую-нибудь простую, но очень важную оптимизацию.


Предыдущие части: 1, 2.

Автор: Анатолий Ализар

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js