Skip to content

Latest commit

 

History

History
837 lines (671 loc) · 96.6 KB

Browser.md

File metadata and controls

837 lines (671 loc) · 96.6 KB

Работа браузера и смежные вопросы

Работа браузера. Оптимизация веб-страниц

  • Общая схема работы

    • Получение ресурсов (Fetching) - скачиваем
    • Парсинг (Parsing)
      • DOM (Document Object Model) — абстрактное представление HTML-документа. Дерево
      • CSSOM (CSS Object Model) — абстрактное представление правил CSS в виде дерева.
        • Чтение стилей приостанавливает чтение кода страницы
        • Благодаря оптимизациям (например, сканеру предзагрузки) стили могут не блокировать чтение HTML,
        • Но они точно блокируют выполнение JS - в скрипте могут использоваться CSS-селекторы для выборки элементов.
      • по ходу натыкается на блокирующие элементы, например скрипты - приостанавливают обработку до своей полной загрузки.
    • Render Tree - объединяет DOM и CSSOM в общее дерево рендеринга
      • в Render tree попадают только видимые элементы.
      • Для элементов у которых display: none, вычисления не будут производиться,
      • элементы с visibility: hidden будут участвовать в Layout/Reflow, так же как и псевдоэлементы, у которых имеется заполненное свойство content (div::before{content:”Hello”}), хотя их нет в DOM.
    • Layout - вычисление позиции и размеров элементов.
      • «Расставляем» элементы на странице -> получаем Layout tree
      • все дальнейшие повторные операции правильнее называть Reflow. Иногда этот процесс называется просто Layout, во всех случаях.
      • Определение размеров и местоположений элементов происходит не за один проход по дереву, проход может происходить несколько раз, если элементы встречающиеся позже, влияют на предыдущие элементы. В целом это очень сложная процедура, требующая значительных вычислительных ресурсов.
      • если элементы не влияют на расположение и размеры других элементов, то их положение и размеры можно просчитать за один подход.
      • Именно поэтому при вёрстке макетов рекомендуется «находиться в потоке» — чтобы браузеру не приходилось несколько раз пересчитывать один и тот же элемент, так страница отрисовывается быстрее.
      • Глобальный Layout — процесс просчёта всего дерева полностью, то есть каждого элемента.
      • Инкрементальный Layout — просчитывает только часть.
    • Paint - отрисовка
      • Repaint для последующих повторных операций.
      • Размера и положения элементов недостаточно чтобы отобразить страницу. Нужно знать каким образом «покрасить» эти элементы. На этапе Paint/Repaint браузер обходит Layout Tree и создает записи о том как будут отрисованы элементы на странице(позиция x,y, ширина, высота, цвет).
      • ресурсоемкий процесс, поэтому для хорошей отзывчивости вашей страницы, необходимо свести к минимуму операции которые вызывают Repaint. Вызвать Repaint могут изменения свойств color, background, visibility и подобных, в общем свойств которые не изменяют размеров и положения элемента
      • Если какие либо из этих свойств изменяются при анимации, тогда происходит Repaint элементов которые были затронуты и слои (об этом подробнее в разделе о Composite) к которым принадлежат эти элементы обрабатываются GPU.
      • каждый раз когда вызывается Reflow, за ним вероятнее всего последует Repaint элемента. То есть если вы измените элементу свойство width, произойдет Reflow, а затем и Repaint затронутых элементов.
    • Композитинг (Compositing) — разделение содержимого страницы на «слои», которые браузер будет перерисовывать
      • Эти слои друг от друга не зависят, из-за чего изменение элемента в одном слое не затрагивает элементы из других слоёв, и перерисовывать их становится не нужно.
      • пора конечной отрисовки элементов на странице. Для этого браузер на этапе Composite группирует различные элементы по слоям, растрирует эти слои, то есть отрисовывает пиксели и затем объединяет эти слои в готовую страницу в отдельном потоке композитора (compositor thread ). Все это делается для повышения производительности страницы. Теперь при скролле страницы достаточно просто сдвинуть в необходимый отрисованный слой и заново объединить слои в потоке композитора.
      • Так как размеры слоев могут быть достаточно большими, поток композитора также разделяет их на части (Tiles) и отрисовывает в первую очередь те части, которые видны в данный момент в окне браузера.
      • Layout, и Paint работают за счёт CPU (central process unit), поэтому относительно медленные. Плавные анимации при таком раскладе невероятно дорогие.
      • Для плавных анимаций в браузерах предусмотрен композитинг (Compositing).
      • Именно из-за разнесения элементов по разным композиционным слоям свойство transform не так сильно нагружает браузер. Поэтому чтобы анимации не тормозили, их рекомендуется делать с применением transform и opacity.
      • этап Composite происходит в отдельном потоке композитора, а не в основном, то вычисления в JS никак не влияют на него. Даже если вся страница подвиснет из-за бесконечного цикла в JS, анимация которая реализована с помощью transform, opacity продолжит свое выполнение.
      • Благодаря тому что элементы расположены на отдельных слоях, Reflow и Repaint для элементов одного слоя не затрагивают элементы на остальных слоях, но бывают исключения
    • Reflow (Relayout, Layout) и Repaint - перестановка и перерисовка
      • Браузер перерисовывает экран каждый раз, когда на странице происходят какие-то изменения.
      • Reflow срабатывает когда вы
        • меняете св-во стиля, которое отвечает за положение и размеры элемента — идёт Reflow всех элементов, на которые могут повлиять эти изменения
        • пытаетесь получить метрики элемента с помощью JS (elem.getBoundingClientRect(), elem.offsetLeft, elem.clientLeft и т.д.),
        • производите скроллинг
        • запускаете выполнение события.
      • Reflow могут быть подвергнуты как отдельные ветки Render Tree, так и все дерево.
      • Чем глубже вложенность элемента в Render Tree — тем больше элементов будут затронуты при Reflow. Поэтому сохраняйте структуру документа как можно более плоской.
      • Так же следует уменьшить количество CSS правил и избавиться от правил которые вы не используете.
      • Layout / Reflow происходит в основном потоке браузера — там же где исполняется JS, крутится Event Loop и т. д. Когда исполняется тяжелый JS-код, Reflow будет блокирован => интерактивность страницы также будет заблокирована.
      • Один цикл обновления (перерисовки страницы) — это animation frame.


  • Дорогие операции

    • "дорогие" операции. Relayout / repaint
    • "дорогие" операции чтения (getComputedStyle() и т.д.)


  • Общие рекомендации

    • Обращаться к DOM как можно реже.
      • Если обратился — сохрани элемент в переменной, чтоб не искать повторно
    • Минимизируйте перерисовку (Repaint) и перестановку (Reflow).
      • Минимизировать изменения компоновки и геометрии (требуют перестановки Reflow, а потом Repaint):
        • Добавляются или удаляются визуальные элементы DOM
        • Элемент меняет положение
        • Элементы меняют размер (из-за полей, отступов, толщины границы, ширины, высоты и т. Д.)
        • Изменения содержимого, например, изменения текста или изображения заменены на другой размер
        • Отрисовка начальной страницы
        • Размер окна браузера изменен
      • Объединить несколько изменений DOM и изменений стиля в один пакет и применить их все сразу.
      • ПОЧЕМУ:
        • Reflow / Relayout. Когда изменяется геометрия элемента (ширина и высота) - браузер пересчитывает геометрическое значение элемента и геометрию / положение других элементов, затронутых изменением. Например, border стал толще или к абзацу добавили текст. Браузер делает недействительными части дерева визуализации и перестраивает дерево визуализации.
        • Repaint - после завершения перекомпоновки браузер перерисовывает затронутую часть,
    • Минимизировать количество запросов информации о макете
      • Избегать получения информации о макете:
        • offset: offsetTop, offsetLeft, offsetWidth, offsetHeight
        • scroll: scrollTop, scrollLeft, scrollWidth, scrollHeight
        • client: clientTop, clientLeft, clientWidth, clientHeight
        • getComputedStyle()
      • В процессе смены стиля лучше не использовать ни один из вышеперечисленных атрибутов.
      • Если запросил — назначь ее локальной переменной, и потом бери оттуда.
      • ПОЧЕМУ:
        • браузеры используют "очереди", чтобы оптимизировать количество Reflow и выполнять их партиями. При запросе информации о макете (смещения, значения прокрутки или вычисляемую информацию о стиле) — браузер обновляет очередь и применяет все изменения, чтобы вернуть обновленное значение.
        • Информация о макете, возвращаемая этими свойствами и методами, должна быть обновлена, поэтому браузер должен выполнить изменения и переформатировать очередь отрисовки, чтобы вернуть правильное значение.
    • Уменьшить количество агентов событий
      • Когда на странице много элементов, и каждый из них привязан к одному или нескольким событиям (например, onclick), это может повлиять на производительность.
      • Чем больше узлов DOM нужно получить и изменить, тем медленнее приложение.
      • Кроме того, дополнительные события требуют времени обработки, и браузеру необходимо отслеживать каждое событие, которое потребляет память.


  • Критические этапы рендеринга (Critical Rendering Path)

    • Последовательность шагов, которые выполняет браузер, когда преобразуется HTML, CSS и JS в пиксели на экране.
    • Оптимизация этих шагов улучшает производительность рендера.
    • CRP состоит из работы с:
      • Document Object Model (DOM),
      • CSS Object Model (CSSOM),
      • деревом рендера (render tree)
      • компоновкой объектов (layout)
    • Объектная модель документа DOM создаётся в тот момент, когда браузер парсит HTML. Этот HTML может запрашивать JavaScript, который может модифицировать DOM. HTML может запросить стили, которые участвуют в создании CSS Object Model. Движок браузера комбинирует эти две объектные модели, чтобы создать дерево рендера (render tree). Компоновка (layout) определяет размеры и позицию каждого элемента на странице. Как только компоновка определена - пиксели отрисовываются на экране.
    • Ссылки



  • Оптимизация рендеринга web-страниц — общее

    • в первую очередь загружать критические запросы (html,css, шрифты...). Т.е. управлять приоритетом загрузки статического контента. Например через <link rel="preload">
    • Использование CSS-спрайтов
    • Уменьшите количество HTTP-запросов. Используйте поддомены для параллельного скачивания
    • Оптимизация изображений - формат, размер, вектор, CSS-графика...
    • Оптимизировать количество шрифтов
    • JS - избегать лишних зависимостей
    • Используйте CDN для загрузки популярных JavaScript библиотек
    • минимизация CSS & JS
    • Разделение кода (code splitting) - ленивая загрузка, динамический импорт... Подгружать не самые важные вещи только когда они понадобятся
    • кэширование - на стороне сервера, на стороне клиента ( HTTP-заголовок Expires )
    • Пять основных областей на которые нужно обратить внимание.
      • JavaScript
        • В предыдущих материалах этой серии мы рассказывали о том, как писать оптимизированный JS-код, не блокирующий пользовательский интерфейс, эффективно использующий память и реализующий другие полезные техники. Когда речь идёт о рендеринге, нам нужно учитывать то, как JS-код будет взаимодействовать с элементами DOM на странице. JavaScript может вносить множество изменений в пользовательский интерфейс, особенно если речь идёт об одностраничных приложениях.
      • Вычисление стилей
        • Это — процесс определения того, какое CSS-правило применяется к конкретному элементу с учётом соответствующих этому элементу селекторов. После определения правил осуществляется их применение и вычисление итогового стиля для каждого элемента.
      • Формирование макета страницы
        • После того, как браузер узнает о том, какие стили применяются к элементу, он может приступить к вычислению того, как много места на экране займёт этот элемент, и к нахождению его позиции. Модель макета веб-страницы указывает на то, что одни элементы могут влиять на другие элементы. Например, ширина элемента может влиять на ширину дочерних элементов, и так далее. Всё это означает, что процесс формирования макета — это задача, требующая интенсивных вычислений. Кроме того, вывод элементов выполняется на множество слоёв.
      • Отрисовка
        • Именно здесь выполняется преобразование всего, что было вычислено ранее, в пиксели, выводимые на экран. Этот процесс включает в себя вывод текста, цветов, изображений, границ, теней, и так далее. Речь идёт о каждой видимой части каждого элемента.
      • Компоновка
        • Так как части страницы вполне могут быть выведены на различных слоях, их требуется совместить в едином окне в нужном порядке, что приведёт к правильному выводу страницы. Это очень важно, особенно — для перекрывающихся элементов.
    • JS
      • не блокировать пользовательский интерфейс
      • эффективно использовать память
      • избегать использования setTimeout() и setInterval() для обновления внешнего вида элементов страниц.
      • переносить длительные вычисления в веб-воркеры.
      • для изменений в DOM использовать микро-задачи, разбитые на N кадров.
    • Прочее
      • уменьшить сложность CSS селекторов.
      • Уменьшите число элементов, для которых вычисляем стили. Лучше менять стиль N элементов, а не всю стр.
      • Стараться не менять этих свойств: ширина, высота, позиция элемента (геометр. характеристики) — они требуют изменения макета.
      • Использовать flexbox вместо старых моделей создания макетов - работает быстрее, дает сильный прирост производительности.
      • Избегайте периодического изменение параметров элементов и их последующего считывания. Т.е. меняю стиль элемента (например, динамически добавляю CSS-класс), а потом считываю его параметры (вроде offsetHeight или offsetWidth) из предыдущего кадра => браузеру надо применить изменения стиля, создать макет и возвратить нужные данные.
      • Избегать анимации свойств элементов, которые вызывают изменение макета страницы (например width и height)


  • Оптимизация JS-кода

    • JavaScript-код часто приводит к изменению того, что можно наблюдать в браузере.
    • Особенно это актуально для одностраничных приложений.
    • Вот несколько советов, касающихся оптимизации JS для улучшения процесса рендеринга страниц.
      • Избегайте использования функций setTimeout() и setInterval() для обновления внешнего вида элементов страниц. Эти функции вызывают коллбэк в некоторый момент формирования кадра, возможно, в самом конце. Нам же нужно вызвать команду, приводящую к визуальным изменениям, в начале кадра, и не пропустить его.
      • Переносите длительные вычисления в веб-воркеры.
      • Используйте для выполнения изменений в DOM микро-задачи, разбитые на несколько кадров. Этим следует пользоваться тогда, когда задача нуждается в доступе к DOM, а доступ к DOM, из веб-воркера, например, получить нельзя. Это означает, что большую задачу нужно разбить на более мелкие и выполнять их внутри requestAnimationFrame, setTimeout, или setInterval, в зависимости от особенностей задачи.


  • Оптимизация CSS

    • Модификация DOM путём добавления и удаления элементов, изменения атрибутов и других подобных действий приведёт к тому, что браузеру придётся пересчитать стили элементов, и, во многих случаях, макет всей страницы, или, по крайней мере, некоторой её части. Для оптимизации процесса рендеринга страницы учитывайте следующее.
      • Уменьшите сложность селекторов. Использование сложных селекторов может привести к тому, что работа с ними займёт более 50% времени, необходимого для вычисления стилей элемента, остальное время уйдёт на конструирование самого стиля.
      • Уменьшите число элементов, для которых нужно выполнять вычисление стилей. То есть, лучше, если изменение стиля будет направлено на несколько элементов, а не на всю страницу.


  • Оптимизация макета

    • Пересчёт макета страницы может требовать серьёзных системных ресурсов.
    • Для оптимизации этого процесса примите во внимание следующее.
      • Уменьшите число ситуаций, приводящих к пересчёту макета. Когда вы меняете стили, браузер выясняет, требуется ли пересчёт макета для отражения этих изменений. Изменения свойств, таких, как ширина, высота, или позиция элемента (в целом, речь идёт о геометрических характеристиках элементов), требуют изменения макета. Поэтому, без крайней необходимости, не меняйте подобные свойства.
      • Всегда, когда это возможно, используйте модель flexbox вместо более старых моделей создания макетов. Эта модель работает быстрее, чем другие, что может дать значительный прирост производительности.
      • Избегайте модели работы с документом, предусматривающей периодическое изменение параметров элементов и их последующее считывание. В JavaScript доступны параметры элементов DOM (вроде offsetHeight или offsetWidth) из предыдущего кадра. Считывание этих параметров проблем не вызывает. Однако, если вы, до чтения подобных параметров, меняете стиль элемента (например, динамически добавляя к нему какой-то CSS-класс), браузеру потребуется потратить немало ресурсов для того, чтобы применить изменения стиля, создать макет и возвратить в программу нужные данные. Это может замедлить программу, подобного стоит избегать всегда, когда это возможно.


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

    • Часто эта задача отнимает больше всего времени, поэтому важно избегать ситуаций, приводящих к перерисовке страницы.
    • Вот что здесь можно сделать.
      • Изменение любого свойства, за исключений трансформаций и изменений прозрачности, приводит к перерисовке. Используйте эти возможности умеренно.
      • Если ваши действия вызвали пересчёт макета, это приводит и к вызову перерисовки страницы, так как изменения геометрических параметров элемента ведут и к его визуальным изменениям.
      • Уменьшайте области страниц, которые необходимо перерисовывать, грамотно управляя расположением слоёв и анимацией.


  • Оптимизация производительности анимаций

    • Как и за всё остальное в этом мире, за анимацию надо платить. При этом анимирование некоторых свойств обходится «дешевле», чем анимирование других. Например, анимирование свойств width и height элемента приводит к изменению его геометрии и может привести к тому, что другие элементы на странице переместятся или изменят размер. Этот процесс называется формированием макета страницы. Об этом мы говорили в одном из предыдущих материалов.
    • В целом, следует избегать анимации свойств элементов, которые вызывают изменение макета страницы или её перерисовку. Для большинства современных браузеров это означает ограничение анимациями opacity и transform.




Метрики производительности веб-приложений

  • Общее

    • Есть много разных метрик - люди смотрят сайт с разных устройств, из разных стран, на разных браузерах, с интернетом разной скорости...
    • Поэтому используют многомерное (многовариантное) тестирование
    • Раньше использовали метрику «PageLoad» — однократное измерение времени открытия страницы. Но сейчас всё сложнее.


  • Core Web Vitals

    • Набор показателей, для измерения фактической производительности веб-сайта
    • Представлен Google в 2019 году.
    • Эти метрики измеряются во всех браузерах на базе Chrome. Для Desktop и Android.
    • Включая робота Googlebot, который использует эти оценки, чтобы влиять на рейтинг страницы.
    • Метрики Core Web Vitals
      • Показатель первого контента (First Contentful Paint, FCP)
        • сколько времени требуется, чтобы показать пользователю, что запрос получен и страница загрузится/
        • Например - отображение title страницы на вкладке браузера
      • Показатель наиболее объемного контента (Largest Contentful Paint, LCP)
        • сколько времени требуется, чтобы браузер отобразил на экране наибольший объем содержимого.
      • Совокупный сдвиг макета (Cumulative Layout Shift, CLS)
        • измеряет, насколько содержимое страницы перемещается по мере загрузки и рендеринга другого содержимого
        • Сдвиги макета, которые передвигают важный контент, действительно неприятны в использовании.
      • Задержка первого входа (First Input Delay, FID)
        • действительно ли страница уже загружена, когда пользователь думает, что видит готовую страницу.
        • Если браузер загружает, анализирует и запускает JavaScript, когда пользователь нажимает на страницу, будет задержка, пока браузер не сможет обработать событие и инициировать событие клика. FID измеряет эту задержку.
      • Время до первого байта (Time To First Byte, TTFB)
        • время, пока сервер не вернет первый байт данных
      • Индекс скорости (Speed Index, SI)
        • измеряет видимые изменения во время загрузки веб-страницы, чтобы определить, когда пользователь считает, что веб-страница загружена.
      • Время до интерактивности (Time to Interactive, TTI)
        • показатель Chrome Lighthouse, который измеряет время, необходимое для того, чтобы страница стала полностью интерактивной, включая отрисовку, завершение JavaScript и завершение браузером своих фоновых задач.
      • Общее время блокировки (Total Blocking Time, TBT)
        • время, когда ввод данных пользователем откладывается из-за фоновых задач браузера, таких как обработка JavaScript или синтаксический анализ CSS.
        • Измеряет, насколько загружен браузер, чтобы загрузить вашу веб-страницу.
      • `` ()


  • Метрики производительности сайта

    • Время появления заголовка
      • от запроса до момента когда заголовок вашего сайта появляется на вкладке браузера
      • определяется скоростью доставки с исходного сервера в браузер пользователя
    • Время рендеринга
      • от запроса до отображения содержимого в окне
    • Время начала взаимодействия
      • от запроса до момента когда пользователь может что-то сделать на странице
    • Время работы DNS
      • сколько требуется провайдеру DNS для преобразования доменного имени в IP-адрес
    • Время соединения
      • от запроса до установления соединения между браузером и сервером
    • Время до первого байта
      • от запроса до получения первого байта
      • Порядок, в котором пользователи получают информацию, важен, и некоторые небольшие изменения в вашем коде могут повысить этот показатель производительности веб-сайта.
      • Статический контент, который кажется одинаковым для всех пользователей, должен быть отделен от динамического контента, специфичного для отдельного посетителя. Таким образом, пользователи сразу же получат ваш контент, ожидая загрузки более медленного персонализированного контента.
    • Время до последнего байта
      • Качество вашего кода и запросов к базе данных играют большую роль в этом показателе.


  • Сложность контента и метрики производительности сайта

    • Общий вес
      • Общее количество байтов, которые получает пользователь.
      • Средний размер страницы в 2010 - 0,7 mb (702 kb)
      • Средний размер страницы в 2016 - 2,3 mb
      • Средний размер страницы в 2022 - 4,6 мб
    • Общее количество assets
      • в данном случае важно именно количество, а не вес каждого. Несколько крупных загрузятся быстрее чем много мелких.
      • Поэтому используется объединение, спрайты картинок и т.д.
      • assets (в данном контексте) — наборы файлов, которые используются на HTML-странице.Файлы css, скрипты, изображения, шрифты... Иногда так называют только css- и js-файлы.
      • Основной подход – все css- и js-файлы собираются в папке, там они объединяются, и уже оттуда они подключаются в HTML-код. При объединении файлов может использоваться сжатие (минификация) – удаление лишних пробелов, переводов строк, комментариев и т.д.
    • Сторонние домены
      • чем меньше ресурсов расположено на сторонних доменах - тем больше контроля.
      • желательно размещать все ресурсы на своем домене или на проверенных доменах, которым доверяю


  • Поведение пользователя и метрики производительности сайта

    • Частота ошибок сайта
      • Среднее количество проблемных запросов по сравнению с общим количеством запросов.
      • Например, может увеличиться количество ошибок при высоких нагрузках - когда много пользователей одновременно запрашивают ресурс с сервера.
    • Показатель отказов
      • когда пользователь быстро уходит с сайта, не просмотрев его толком
      • Возможными причинами высоких показателей отказов могут быть плохо подобранные ключевые слова, медленная загрузка или неприятный графический дизайн.
    • Топ страниц
      • отслеживать какие страницы сайта самые популярные => можно сделать вывод: что нужно пользователям, и доработать сайт
    • Показатель конверсии
      • позволяет вам узнать, делают ли пользователи то, что вы хотите, когда они посещают ваш сайт.
      • Коэффициент конверсии рассчитывается путем простого деления количества уникальных посетителей на количество конверсий.


  • Реальная и воспринимаемая производительность

    • Прежде всего важна «воспринимаемая произодительность».
    • Например, реализация ленивой загрузки технически может сделать ваш сайт быстрее, но добавление индикатора прогресса к отдельным ресурсам по мере их загрузки заставляет пользователей лучше осознавать проходящее время, поэтому они на самом деле воспринимают сайт как загружаемый медленно. Если вы собираетесь использовать ленивую загрузку, не забудьте убрать индикатор.



WebAssembly

  • Общее

    • WebAssembly (WASM) — бинарный формат, позволяющий запускать код в браузере
    • Точнее: бинарный формат инструкций для стековой виртуальной машины. WebAssembly спроектирован как портативная цель компиляции для высокоуровневых языков, таких как C/C++/Rust, которую можно развертывать в web для клиентских и серверных приложений.
    • Представляет собой переносимое абстрактное синтаксическое дерево, обеспечивающее как более быстрый анализ, так и более быстрое выполнение кода, чем JS.
    • Это эффективный низкоуровневый байт-код для веб-приложений. Wasm даёт возможность разработки функционала веб-страниц на языках, отличных от JavaScript (например, это C, C++, Rust и другие). Код на этих языках компилируется (статически) в WebAssembly. В результате получается веб-приложение, которое быстро загружается и отличается очень высокой производительностью.
    • НЕ язык программирования, а байт-код. Мы же не называем Java-байткод языком программирования.
    • Загружается в браузер и исполняется в браузере. Формально, WebAssembly исполняется JavaScript-движком, а не самим браузером, поэтому есть и другие варианты исполнения, например, под NodeJS.
    • Исполняется виртуальной машиной. Это простая стековая машина с памятью, простота позволяет легко реализовать её для любого современного процессора.
    • НЕ имеет ничего общего с Web, кроме того что общается с внешним миром через JavaScript. Действительно, WebAssembly это просто виртуальная машина, имеющая память и исполняющая инструкции.


  • Зачем?

    • быстро исполнять код в браузере. Быстрее чем JavaScript — в идеале, со скоростью света родного кода нашего процессора.

    • Zero configuration — решение «из коробки», без установки, нужен только браузер.

    • Безопасно — новая технология не должна создавать новых угроз.

    • Кросс-платформенно — у нас есть несколько платформ, включая мобильные, несколько операционных систем.

    • Удобно для разработчиков — нужны удобные средства разработки и отладки.

    • В принципе,эту задачу решает JS. Что плохо: нужен плагин и/или runtime ⇒ нет zero configuration.

    • У JS есть внутренние ограничения, которые уже не позволят сделать его радикально быстрее.

    • Потенциальные альтернативы (не прижились):

      • NaCl (Native Client) - Google
      • PNaCl (Portable Native Client) - LLVM IR subset.
      • asm.js - Mozilla


  • Преимущества

    • Скорость — почти как родной код.
    • Эффективность — бинарный формат, быстрый парсинг и компиляция.
    • Портируемость — все браузеры и операционные системы.
    • Безопасность — запуск в sandbox.
    • Удобство отладки — поддержка отладки в браузерах, отладчик есть уже сейчас.
      • Открытый стандарт — то есть это уже не инициатива отдельной компании, пытающейся «перетянуть одеяло на себя». Стандарт уже принят, в 2017 году.


  • Время загрузки

    • Для того, чтобы запустить JavaScript-программу, браузеру сначала нужно загрузить все .js-файлы, которые хранятся и передаются по сети в виде обычного текста.
    • Wasm — это низкоуровневый язык, похожий на ассемблер. WebAssembly-программы загружаются браузером быстрее, так как через интернет нужно передать уже скомпилированные файлы в весьма компактном бинарном формате.


  • Выполнение

    • Сегодня wasm-программы выполняются лишь на 20% медленнее чем машинный код. Это, без сомнения, достойный результат. Ведь речь идёт о формате, который компилируется в особом окружении и запускается с применением множества ограничений, которые обеспечивают высокий уровень безопасности. Подобное замедление в сравнении с машинным кодом в этом свете выглядит не таким уж и большим. Кроме того, в будущем ожидается повышение производительности wasm-кода.
    • Ещё интереснее то, что wasm платформенно-независим. Его поддержка имеется во всех ведущих браузерных движках, которые демонстрируют примерно одинаковую производительность при выполнении wasm-кода.


  • Оптимизация кода

    • Если рассматривать wasm в конвейере JS-движка, то окажется, что wasm-код не нуждается в анализе и в нескольких проходах компиляции. Он уже оптимизирован и готов к использованию. Т.е. мы проскакиваем несколько трудозатратных стадий.
    • Wasm-код оптимизируется в ходе статической компиляции. При работе с ним не нужно разбирать текстовые файлы. Благодаря wasm в нашем распоряжении оказываются бинарные файлы, которые достаточно лишь преобразовать в машинный код. Все улучшения в этот код были внесены при компиляции, которая производится до того, как он попадает в браузер. Всё это делает выполнение wasm гораздо более эффективным, так как немало шагов по превращению текста программы в оптимизированный машинный код можно пропустить.


  • Заметки

    • WebAssembly - это просто куски кода внутри js-программы которые работают максимально быстро.
    • Также и WebCL(использование параллельных вычеслений на видеокарте)
    • Просто js работает в 2-5 раз медленнее чем аналогичная программа на Си (производительность отжирает интерпретатор).
    • Для преодоления этой проблемы в js внедряют WebAssembly и WebCL чтобы добиться максимально возможной производительности
    • Улучшение JavaScript: Реализуйте все критичные вещи на wasm и импортируйте его как стандартный JavaScript модуль.
    • WebAssembly определяет абстрактное синтаксическое дерево (как и JavaScript) в бинарном формате. Вы можете писать код и чистить его от ошибок в текстовом формате. WebAssembly легко читаем.
    • Улучшение для браузеров: Браузеры будут понимать бинарный формат, а это значит, что разработчики смогут компилировать бинарники, которые можно сжать гораздо больше, чем используемые сегодня текстовые файлы с JavaScript. Чем меньше файл, тем быстрее загрузка. В зависимости от возможностей оптимизации времени компиляции, код на WebAssembly может передаваться и запускаться быстрее, чем на JavaScript!
    • Цель для компиляции: Возможность другим языкам, получить первоклассную двоичную поддержку через весь стек веб-платформы.
    • WebAssembly может увеличить скорость JavaScript в разы!
    • WebAssembly позволяет использовать больше языков в веб-разработке
    • WebAssembly добавляет вещи, которые большинство JS разработчиков не хотят видеть в JavaScript. Сама функциональность нужна, но вот в JavaScript ей места точно нет. Тем более, что мы можем получить все эти функции с помощью компиляции с других языков программирования.
    • Фактически, WebAssembly предоставляет нам альтернативный компилятор — созданный специально для этих целей.
    • Теперь, нам будет гораздо легче портировать код, который сильно зависит от, например, совместно используемых цепочек памяти. Я уверен, что написать компилятор для WebAssembly будет легче, чем написать компилятор для JavaScript, а все потому, что первый гарантирует лучший перенос функций языка в заданное абстрактное синтаксическое дерево.
    • То, что все старые языки программирования теперь без проблем могут быть использованы в Сети — это хорошо, однако главное не в этом.
    • WebAssembly является отличным основанием для разработчиков начать работу над новыми языками программирования.
    • WebAssembly или wasm – это низкоуровневый формат байт-кода для клиентских скриптов на стороне браузера.
    • При компиляции в WebAssembly вы делаете свою программу доступной для всех платформ, на которых поддерживается wasm, другими словами, для всех браузеров (и не только)
    • На практике WebAssembly реализуется разработчиками браузеров на основе существующего JavaScript-движка. По сути, он предназначен для замены JavaScript как целевого языка. Например, вместо компиляции TypeScript в JavaScript его разработчики теперь могут компилировать свой код в WebAssembly. Иными словами, это не новая виртуальная машина, это новый формат для той же самой виртуальной машины JavaScript, которая включена в каждый браузер. Это позволит использовать существующую инфраструктуру JavaScript без использования самого JavaScript.
    • Во-первых, новый формат WebAssembly обещает значительное увеличение производительности парсинга - тип бинарного формата, используемый в WebAssembly, может быть декодирован гораздо быстрее, чем JavaScript может быть пропарсен (эксперименты показывают более чем 20-кратную разницу). Это позволит использовать в вебе ПО, которое раньше было бы нецелесообразно разрабатывать, например: виртуальные машины, виртуальную реальность, распознавание изображений и многое другое.
    • Больше не придётся использовать JavaScript для веба, только потому что это единственное, что выполняется в браузере. JavaScript имеет плохую репутацию, хотя на самом деле это хороший язык в том, для чего он предназначен: позволяет быстро писать небольшие скрипты. Однако в настоящее время вы вынуждены использовать его для всего, что запускается в вебе, и это проблема для многих крупных проектов.
    • WebAssembly можно будет переносить на другие платформы. Это означает, что, если вы пишете программное обеспечение на языке, который компилируется в WebAssembly, вы сможете запустить его на .NET.
    • В отличие от других подходов для достижения нативного опыта, WebAssembly не требует встроенных плагинов, а запускается внутри веб-платформы. Это значит, что разработчики могут интегрировать библиотеки WebAssembly для сложных вычислительных процессов (сжатие данных, распознавание лиц) в существующие JavaScript-приложения для снижения нагрузки.
    • WebAssembly – это инициатива, направленная на создание безопасного, переносимого и быстрого для загрузки и исполнения формата кода, подходящего для Web. WebAssembly – это не язык программирования. Это – цель компиляции, у которой имеются спецификации текстового и бинарного форматов. Это означает, что другие низкоуровневые языки, такие, как C/C++, Rust, Swift, и так далее, можно скомпилировать в WebAssembly. WebAssembly даёт доступ к тем же API, что и браузерный JavaScript, органично встраивается в существующий стек технологий. Для компиляции кода в формат WebAssembly используется Emscripten.
    • Emscripten – это компилятор из байт-кода LLVM в JavaScript. То есть, с его помощью можно скомпилировать в JavaScript программы, написанные на C/C++ или на любых других языках, код на которых можно преобразовать в формат LLVM.
    • Веб-приложения, написанные на WebAssembly, могут запускаться на скорости, близкой к нативной, потому что весь код анализируется и компилируется преждевременно. Браузер сразу видит инструкции на машинном языке, которые он может сразу проверить, оптимизировать и запустить.
    • В каком-то смысле WebAssembly меняет работу веб-разработчика и фундаментальные свойства веба. С помощью WebAssembly и сопутствующего набора инструментов программы, написанные на C и C++, могут быть перемещены в веб для запуска с близкой к нативным приложениям производительностью. Мы ожидаем, что, с развитием WebAssembly, вы сможете поступать так же с языками создания мобильных приложений – то есть, Java, Swift и C#.



Web Worker API

  • Общее

    • Веб-воркеры — это потоки, принадлежащие браузеру, которые можно использовать для выполнения JS-кода без блокировки цикла событий. Введены в HTML 5.
    • Ещё раз: это часть браузерного API! Не является частью JS. Просто из JS можно взаимодействовать с этими возможностями браузера.
    • Веб-воркеры не реализованы в Node.js — там есть концепция «кластеров» или «дочерних процессов», а это уже немного другое.
    • Позволяет частично снять ограничения, которые накладывает на JS концепция однопоточности.
    • Веб-воркеры позволяют разработчику размещать задачи, для выполнения которых требуются длительные и сложные вычисления, интенсивно задействующие процессор, в фоновых потоках, без блокировки пользовательского интерфейса, что позволяет приложениям оперативно реагировать на воздействия пользователя.
    • Веб-воркеры позволяют выполнять тяжёлые в вычислительном плане и длительные задачи без блокировки потока пользовательского интерфейса. На самом деле, при их использовании вычисления выполняются параллельно. Перед нами настоящая многопоточность. Они отлично подходят для того, чтобы выполнять тяжёлые вычислительные операции, не замедляя работу пользовательского интерфейса.
    • Web workers создаются в отдельных js-файлах. Выполняются в изолированных потоках в браузере.
    • Страница создаёт web-worker (используя специальный файл), браузер создаст новый поток, который асинхронно загрузит этот файл. Страница, создавшая веб-воркер, может взаимодействовать с ним. Например - обмениваться с ним данными, используя JSON-объект.
    • Когда воркер получает сообщение и понимает, чего от него хотят, он будет выполнять вычисления самостоятельно, не блокируя цикл событий. То, чем занимается воркер, выглядит как стандартная JS-функция. Когда вычисления завершены, их результаты передаются главной странице.


  • Ограничения

    • Веб-воркерам, из-за их многопоточной сущности, доступен лишь ограниченный набор возможностей JavaScript - из них нельзя менять DOM, вызывать методы объектов window, document, parent и ещё много чего. Всё это значит, что веб-воркеры не могут манипулировать DOM (и, таким образом, не могут прямо влиять на пользовательский интерфейс). Поначалу может показаться, что это значительно усложняет использование веб-воркеров, однако со временем, узнав о том, как правильно использовать веб-воркеры, вы начнёте воспринимать их как отдельные «вычислительные машины», в то время как то, что относится к работе с пользовательским интерфейсом, будет выполняться в коде страницы. Воркеры будут выполнять тяжёлые вычисления, и после того, как работа будет завершена, отправлять результаты на страницу, вызывающую их, код которой уже внесёт необходимые изменения в пользовательский интерфейс.


  • Сценарии использования веб-воркеров

    • Рендеринг трёхмерных сцен
    • Шифрование
    • Предварительная загрузка данных.
    • Прогрессивные веб-приложения. Прежде всего - работа с хранилищем данных на стороне клиента (IndexedDB или похожее API)
    • .
    • Проверка правописания.



Service Worker API

  • Общее

    • Сервис-воркеры — это разновидность веб-воркеров.
    • Это API позволяет приложениям поддерживать оффлайновые сценарии работы, даёт программисту контроль над тем, как приложение взаимодействует с внешними ресурсами. Включает механизмы перехвата запросов, возврата кэшированных данных и кэширования новых материалов.
    • Service worker это скрипт, который выполняется браузером в фоне, отдельно от веб-страницы и способен выполнять функции для которых не требуется взаимодействие со страницей или пользователем. На практике Service Worker API позволяет делать такую магическую вещь, как кеширование файлов онлайн веб-приложения на локальное устройство пользователя и затем работать полностью в оффлайне, если нужно. В будущем планируется добавить такие классные вещи как синхронизация кеша в фоне, то есть даже если пользователь не находится сейчас на вашем сайте, сервис-воркер все равно сможет запуститься и скачать обновления например. А также доступ к PushApi из фона опять же (то есть при получении обновления отправить вам пуш-уведомление).


  • Важные характеристики

    • Они выполняются в собственном глобальном контексте, ServiceWorkerGlobalScope.
    • Они не привязаны к конкретной странице.
    • Они не имеют доступа к DOM.
    • Работают только по https
    • Жизненный цикл сервис-воркера не имеет ничего общего с жизненным циклом веб-страницы. Воркер регистрируется в API браузера и продолжает работать, даже когда вкалдака с сайтом закрыта.


  • Некоторые сценарии использования

    • Push-уведомления. Они позволяют пользователям настраивать периодические уведомления, поступающие из веб-приложений.
    • Фоновая синхронизация. Этот механизм даёт возможность откладывать выполнение неких действий до тех пор, пока у пользователя не будет стабильного соединения с интернетом. При использовании системы фоновой синхронизации разработчик может быть уверен в том, что если пользователь, скажем, хочет сохранить изменения документа, отредактированного в веб-приложении без доступа к сети, эти изменения не пропадут.
    • Периодическая синхронизация (ожидаемая возможность). Это API, которое предоставляет функционал для управления периодической фоновой синхронизацией.
    • Работа с геозонами (ожидаемая возможность). Данная возможность позволяет приложению предоставлять пользователю полезный функционал на базе его географического положения, и, в частности, основываясь на событиях попадания пользователя в заранее заданную область.



Веб push-уведомления (Push API и Notifications API)

  • Технология позволяет пользователям подписываться на периодические уведомления веб-приложений. Сообщают подписчикам о появлении новых материалов, или возникновении иных событий.
  • Одним из механизмом, обеспечивающих работу push-уведомлений, являются сервис-воркеры.
  • Пользователь получит сообщение, даже если у него не открыта вкладка с данным сайтом — достаточно просто запустить браузер.
  • Пользователь получит сообщение, даже если оно произошло некоторое время назад, например вчера.
  • Это достигается благодаря тому, что:
    1. используются промежуточные push-сервисы, например Google FСM. Т.е. новостной сайт отправляет сообщение не напрямую в мой браузер, а специальному сервису в Интернете. Сервис ставит сообщение в очередь и отправляет его нужному браузеру
    2. у каждого push-сообщения есть "время жизни" (специальный параметр, задаётся прис оздании сообщения). Пока это время не истекло - push-сервис будет пытаться отправить сообщение браузеру.
  • Работает это всё только в сравнительно новых браузерах, которые поддерживают Push API и Notifications API.
  • Сервер тоже надо настроить, чтоб он мог отсылать эти самые push-сообщения
  • Ключи
    • Ещё там есть ключи (открытые и закрытые) - чтоб сервис push-уведомлений знал, какой сервер приложения подписал пользователя, и был уверен что это — тот же самый сервер, который отправляет уведомления конкретному пользователю. Браузер передаёт applicationServerKey (открытый ключ) push-сервису в ходе оформления подписки. Это означает, что push-сервис сможет связать открытый ключ приложения с подпиской.
  • Server Push
    • HTTP/2 вводит технологию Server Push, которая позволяет серверу отправлять данные в клиентский кэш по собственной инициативе. Однако, при использовании этой технологии данные нельзя отправлять прямо в приложение. Данные, отправленные сервером по своей инициативе, обрабатывает браузер, при этом нет API, которые позволяют, например, уведомить приложение о поступлении данных с сервера и отреагировать на это событие.
    • Именно в подобной ситуации весьма полезной оказывается технология Server-Sent Events (SSE). SSE — это механизм, который позволяет серверу асинхронно отправлять данные клиенту после установления клиент-серверного соединения.
  • Ссылки


SSE API (Server-Sent events)

  • Альтернатива WebSocket.
  • Ещё один вариант API, который предоставляет браузер для COMET-взаимодействия.
  • Позволяет серверу асинхронно отправлять данные клиенту после установления клиент-серверного соединения
  • Технология SSE основана на HTTP, т.е. нет необходимости вводить новый протокол (WebSocket) - а это важное преимущество (безопасность, простоат, настройка сервера)
  • Ссылки


MutationObserver API - отслеживание изменений в DOM

  • Общее

    • Web API, предоставляемое современными браузерами и предназначенное для обнаружения изменений в DOM. С помощью этого API можно наблюдать за добавлением или удалением узлов DOM, за изменением атрибутов элементов, или, например, за изменением текстов текстовых узлов.
    • Общая логика такая:
      • В js коде объявляю, что хочу наблюдать за мутациями на этой странице. Объявляю о своём намерении я при помощи создания нового экземпляра объекта MutationObserver.
      • Там же указываю, что делать при появлении мутации. Например выводить сообщение в консоль, или запускать какую-то функцию
      • После этого запускаю наблюдение, вывзывая у объекта MutationObserver метод observe. Здесь я указываю, за каким DOM-элементом я буду наблюдать. Все его потомки будут отслеживаться автоматически
      • Метод disconnect останавливает наблюдение за изменениями.
      • Метод takeRecords возвращает текущую очередь экземпляра MutationObserver, после чего очищает её. (пока не понял, что это значит)


  • Альтернативы MutationObserver

    • Опрос (polling).
    • Механизм MutationEvents.
    • CSS-анимация.


  • Опрос

    • Самый простой и незамысловатый способ отслеживания изменений DOM — опрос. Используя метод setInterval можно запланировать периодическое выполнение функции, которая проверяет DOM на предмет изменений. Естественно, использование этого метода значительно снижает производительность веб-приложений.


  • MutationEvents

    • API MutationEvents было представлено в 2000 году. Несмотря на то, что это API позволяет решать возлагаемые на него задачи, события мутации вызываются после каждого изменения DOM, что, опять же, приводит к проблемам с производительностью. Теперь API MutationEvents признано устаревшим и вскоре современные браузеры перестанут его поддерживать.


  • CSS-анимация

    • Идея заключается в создании анимации, которая будет вызвана после того, как элемент будет добавлен в DOM. В момент запуска анимации будет вызвано событие animationstart. Если назначить обработчик для этого события, можно узнать точное время добавления нового элемента в DOM. Время выполнения анимации при этом должно быть настолько маленьким, чтобы она была практически незаметна для пользователя.
    • Делаем очень короткую анимацию и навешиваем её ко всем узлам-потомкам нужного DOM-элемента . Когда анимация заканчивается, вызывается соответствующее событие.
    • Разумеется, нужна JS-функция, которая будет играть роль обработчика событий.
    • По сути, навешиваем обработчик события на на родительский элемент, при его изменении вызывается сверх-быстрая (невидимая) анимация, а когда она закончилась - вызывается нужная нам js-функция... Костыль, короче.
    • встроенный объект, наблюдающий за DOM-элементом и запускающий колбэк в случае изменений. может реагировать на изменения в DOM: атрибуты, добавленные/удалённые элементы, текстовое содержимое. Можем использовать его, чтобы отслеживать изменения, производимые другими частями нашего собственного кода, а также интегрироваться со сторонними библиотеками.



WebSocket


WebRTC и механизмы P2P-коммуникаций

  • Real Time Communication - связь в режиме реального времени.
  • WebRTC, позволяет веб-приложениям создавать P2P-соединения (peer-to-peer, соединения типа «точка-точка», одноранговые, пиринговые сети).
  • Например - создание чата.
  • Ссылки


Shadow DOM *


Web-компоненты, пользовательские элементы (Custom Elements)

  • Позволяет создавать свои собственные элементы HTML, наподобии «вшитых» в браузер HTML-тэгов типа <slelct> или <>.
  • Компактные, модульные и подходящие для повторного использования. Объединяют вёрстку, оформление и некоторую логику.
  • Некоторые фреймворки (такие, как Angular или React) пытаются решить ту же проблему, которую решают пользовательские элементы, вводя собственные концепции. Пользовательские элементы можно сравнить с директивами Angular или с компонентами React. Однако пользовательские элементы — это стандартная возможность браузера, для работы с ними не нужно ничего, кроме обычных JavaScript, HTML и CSS. Конечно, это не позволяет говорить о том, что они являются заменой для обычных JS-фреймворков. Современные фреймворки дают нам гораздо большее, нежели лишь возможность имитировать поведение пользовательских элементов. В результате можно говорить о том, что и фреймворки, и пользовательские элементы — это технологии, которые можно использовать совместно для решения задач веб-разработки.
  • Ссылки


Системы хранения данных



Ссылки




Legmo, 2019-2023