Когда-то почти все сайты были статичными. Для любого посетителя они отображали одинаковый контент. Индивидуально наполнять страницы позволила концепция серверного программирования с появлением скриптов CGI (Common Gateway Interface). JavaScript позволил программировать динамические веб-страницы на стороне клиента, не загружая при этом сервер. Стандартные браузеры мотивируют фронтенд-разработчиков использовать различные веб-API через интерфейсы JavaScript. Технология WebAssembly позволяет запускать в веб-браузере программу на C за счет вычислительных ресурсов пользователя.
Новые API имеют расширенные возможности и даже способны заменить популярные фронтенд-библиотеки. Например, аналогичными представляются возможности стандартного DOM API и библиотек манипулирования DOM, таких как JQuery. Встраиваемые API для очистки начали заменять популярные библиотеки. Таким образом, встроенные API браузера помогают писать актуальный, стандартный, совместимый и компактный код без использования сторонних библиотек.
Рассмотрим полезные API-интерфейсы и функции браузера. Они пригодятся в веб-приложениях, библиотеках и экспериментах, а также не увеличивают внешними зависимостями размер пакета приложения. Знание этих механизмов поможет лучше понять внутреннюю структуру веб-проекта даже при использовании полнофункциональных фреймворков.
API пользовательских событий
В браузере среда выполнения JavaScript является однопоточной, а обработка — многопоточной. Браузер отправляет события в очередь JavaScript, помогающую выполнять асинхронную, неблокирующую разработку. Функции всплытия и распространения событий DOM помогают улучшать взаимодействие с веб-интерфейсами. Большинство веб-API используют для событий DOM заранее определенные имена (например, onlick
, onkeydown
и т. д.) , но в браузере поддерживаются и пользовательские события.
API пользовательских событий предлагает использовать различные браузерные события, позволяя разработчикам прикреплять к ним инициирующие программный запуск полезные данные. Получается очень краткое API. Новое пользовательское событие можно отправить подобным образом:
window.dispatchEvent(new CustomEvent('mycustomevent', {
detail: {
msg: 'Hello'
}
}));
Также очень просто подписаться на пользовательское событие и получить доступ к его полезной нагрузке:
window.addEventListener('mycustomevent', (evt) => {
console.log(evt.detail.msg); // Hello
});
Более того, эти пользовательские события можно сделать отменяемыми и всплываемыми с помощью элементов DOM как предопределенных событий. Несомненно, отличным вариантом является использование пользовательских событий в качестве глобального решения обработки событий.
Использование встроенного API-интерфейса Sanitizer
Рендеринг динамического HTML обычно выполняют через шаблоны в MVC-подобных интерфейсных средах, изменяя переменные шаблона. Если не использовать какую-либо платформу внешнего интерфейса, то для визуализации динамических данных в HTML подходит свойство DOM InnerText
. В обоих сценариях вы в конечном итоге получите необработанную HTML-строку, если попытаетесь использовать HTML-код в переменной шаблона. Но в некоторых сценариях необходимо визуализировать HTML-код, который хранится в переменных JavaScript. Рендеринг кода HTML непосредственно из строки JavaScript — хорошо известная уязвимость. Например, сайт со следующим фрагментом уязвим в случае взлома сервера:
const rawHTML = await getRawHTMLFromServer();
docArea.innerHTML = rawHTML;
Если сервер отправит вредоносный код JavaScript, docArea
выполнит его как обычно. Концепция очистки Sanitizer помогает удалять такие опасные теги, как <script/>
, делая строки HTML безопасными для рендеринга в DOM:
docArea.innerHTML = sanitize(rawHTML); // удаление <script> и пр.
Не все интерфейсные фреймворки автоматически выполняют санацию. Поэтому для этой цели и стали столь популярны библиотеки.
Но теперь в современных браузерах есть экспериментальный встроенный API-интерфейс очистки. Он позволяет быстро очищать узлы DOM без повторного анализа строки HTML:
const sanitizer = new Sanitizer();
const rawHTML = await getRawHTMLFromServer();
docArea.replaceChildren(sanitizer.sanitizeFor('div', rawHTML));
Ярлыки API для манипуляций и обхода DOM
Примерно 10 лет назад динамические веб-приложения создавали с помощью JQuery и AJAX, обновляя DOM вручную. Сейчас для автоматического обновления DOM при изменении состояния приложения обычно используют популярные библиотеки внешнего интерфейса. Но иногда по-прежнему используют и минимальное ручное манипулирование DOM, неизбежное в отдельных случаях.
Раньше для манипулирования и обхода DOM использовали JQuery, поскольку встроенный API DOM был немного громоздким. Но теперь более продуктивные функции встроенного API могут заменить и JQuery. Рассмотрим несколько примеров простого манипулирования именами классов CSS:
headerElm.classList.replace('cl-green', 'cl-red');
headerElm.classList.toggle('active');
Выбрать элементы DOM с помощью селектора так же просто, как с и JQuery, например:
const activeStepNodes = document.querySelectorAll('.app .steps li.active');
Для запроса гиперссылок в веб-документе не требуются селекторы запросов — можно использовать предварительно инициализированное свойство:
const linkNodes = document.links;
Такую же производительность, что и JQuery, обеспечивают связанные с DOM и доступные в стандартных браузерах методы:
const titleNode = mainSection.closest('.title');
titleNode.after(subTitleNode);
titleNode.prepend(bulletNode);
Теперь благодаря встроенным API даже плавная прокрутка, добавление анимации и прочие функции возможны без JQuery. Узнать больше о стратегиях манипулирования DOM с помощью лишь обычных веб-API можно в репозитории GitHub.
Полезные события в современных приложениях
Будучи полезной и удобной для разработки средой, браузер генерирует множество полезных для разработчиков событий JavaScript. Их можно использовать для создания современных производительных веб-приложений. Рассмотрим некоторые из них.
Когда неактивна одна из вкладок, на которой находится приложение, следует избегать опросов, интенсивной обработки и воспроизведения мультимедиа. Кроме того, стоит поприветствовать пользователя, когда он выбирает вкладку, неактивную прежде. Реализовать эти функции помогает API видимости страницы, который уведомляет об изменениях состояния видимости:
document.addEventListener('visibilitychange', () => {
console.log(document.visibilityState); // 'visible' или 'hidden'
});
Новое продуктивное и полезное (экспериментальное) событие scrollend
помогает реализовать такие функции, как бесконечная прокрутка, даже без использования проверок границ на основе if
:
document.addEventListener('scrollend', async () => {
await loadItems();
});
Теперь не нужно использовать опрос AJAX для определения статуса сети онлайн/оффлайн. Новые встроенные сетевые события могут определять статус подключения к интернету:
window.addEventListener('online', () => {
console.log('online');
});
window.addEventListener('offline', () => {
console.log('offline');
});
Кроме того, чтобы помочь разработчикам в создании современных приложений, сейчас стандартные браузеры поддерживают добавление прослушивателей событий буфера обмена, изменения размера окна, изменения ориентации устройства и прочее.
WebAssembly и Worker API для современных приложений
Прежде каждое веб-приложение обычно выполнялось в одном потоке на основе JavaScript с несколькими исходными скриптами. Такой подход к разработке был достаточно хорош для любого веб-приложения, поскольку требующие ресурсов задачи выполнялись на сервере. Но сегодня разработчики стремятся использовать вычислительную мощность на стороне клиента, чтобы по максимуму избежать проблем из-за задержек в сети, снизить нагрузку на сервер.
Теперь в браузере можно запускать программы на C, Rust, Go, Python и Zig, скомпилировав их как программы WebAssembly. Это позволяет запускать имеющуюся серверную логику на стороне клиента, даже не переписывая ее на JavaScript. Рассмотрим следующую функцию Zig в файле add.zig
:
export fn add(a: i32, b: i32) i32 {
return a + b;
}
Файл Wasm можно создать следующим образом:
zig build-lib -target wasm32-freestanding -dynamic add.zig
Наконец, экспортированную выше функцию Zig можно вызвать из JavaScript:
<html>
<body>
<script>
fetch('add.wasm').then(r => r.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes)
).then(r => {
const add = r.instance.exports.add;
console.log(add(10, 20));
});
</script>
</body>
</html>
С другой стороны, концепция веб-воркеров помогает запускать ресурсоемкий код в отдельном экземпляре выполнения JavaScript, не блокируя основной поток рендеринга:
const wr = new Worker('background_task.js');
wr.onmessage = (e) => console.log(e.data);
Это позволяет перенести задачу с сервера на сторону клиента, не влияя на производительность пользовательского интерфейса приложения.
API DOM Observer для перспективных пользовательских интерфейсов
Возможностей пришедшего из эпохи IE традиционного DOM API для обычной разработки ранее хватало. Но в современных приложениях с продуктивными функциями требовались обходные варианты. Сегодня API DOM Observer помогает внедрять такие новые функции, как бесконечная перезагрузка, отмена-повтор, адаптивные системы виджетов и другие, без использования обходных путей и сторонних библиотек.
Примеры использования DOM Observer.
ResizeObserver
: реализация адаптивных, отзывчивых виджетов.IntersectionObserver
: запуск действий, когда определенный элемент DOM виден (или невидим) в текущем окне просмотра, т. е. отложенная загрузка изображений во время прокрутки.MutationObserver
: обнаружение изменений элемента DOM, т. е. для реализации отмены-повтора и т. д.
Заключение
Рассмотренные новые функции API браузера помогают создавать современные веб-приложения, повышая производительность разработчика. Грамотному специалисту необходимы стандартные веб-API, поскольку они полезны для технического анализа перед реализацией функции или обоснования необходимости сторонней библиотеки. Кроме того, полезно следить за драфтами W3C, поскольку они помогают прогнозировать появление новых API браузера.
Многие пользователи часто обновляют браузеры, поэтому размер пакета приложений можно даже уменьшить, заменив код сторонней библиотеки нативными фрагментами кода на основе API. Но некоторые полезные веб-API все еще экспериментальные и не включены по умолчанию во многие браузеры. Поэтому перед использованием нативного браузерного API необходимо учитывать совместимость браузера и статус стандартизации.
Читайте также:
- 4 недооцененных API браузера
- Как обеспечить работу современного кода JavaScript во всех браузерах
- Событийно-ориентированная разработка на основе браузерного расширения
Читайте нас в Telegram, VK и Дзен
Перевод статьи Shalitha Suranga: New Browser APIs That Every Web Developer Should Know