Ваня Акулов (@iamakulov_channel) справедливо спрашивает, зачем нужна эта обёртка — я не объяснил, в чём проблема.
Представьте, что в футере вашего SPA есть ссылка на страницу «о проекте». При клике по этой ссылке совершается динамический переход на нужную страницу, но даже после перехода фокус так и остаётся на ссылке. Из-за этого пользователи экранных читалок даже не узнают, что страница поменялась — для них это воспринимается так, будто никакого перехода и не было. Поэтому нужно после динамических переходов переносить фокус на контейнер страницы — тогда экранная читалка после клика по ссылке не будет молчать, а озвучит что-то вроде «Содержимое страницы, 5 элементов». Ну и если вы после динамического перехода нажмёте tab, фокус перейдёт на первый интерактивный элемент внутри страницы, а не на то, что располагалось после кликнутой ссылки.
Представьте, что в футере вашего SPA есть ссылка на страницу «о проекте». При клике по этой ссылке совершается динамический переход на нужную страницу, но даже после перехода фокус так и остаётся на ссылке. Из-за этого пользователи экранных читалок даже не узнают, что страница поменялась — для них это воспринимается так, будто никакого перехода и не было. Поэтому нужно после динамических переходов переносить фокус на контейнер страницы — тогда экранная читалка после клика по ссылке не будет молчать, а озвучит что-то вроде «Содержимое страницы, 5 элементов». Ну и если вы после динамического перехода нажмёте tab, фокус перейдёт на первый интерактивный элемент внутри страницы, а не на то, что располагалось после кликнутой ссылки.
Определяем видимость элемента с IntersectionObserver
Недавно на работе была задача залогировать событие просмотра блока на сайте. Я как представил, что нужно подписываться на событие скролла и вручную считать, входит ли элемент целиком во вьюпорт... А затем вспомнил про
IntersectionObserver
это новый браузерный API, позволяющий асинхронно следить за степенью пересечения элемента с вьюпортом или другим элементом. С его помощью можно определить, виден ли элемент на экране, если виден, то насколько (целиком или частично), а также когда именно он оказался виден. Пример того, где это может потребоваться — модуль для ленивой загрузки картинок.Недавно на работе была задача залогировать событие просмотра блока на сайте. Я как представил, что нужно подписываться на событие скролла и вручную считать, входит ли элемент целиком во вьюпорт... А затем вспомнил про
IntersectionObserver
, прочитал документацию и обрадовался, потому что с ним задача решается гораздо проще и красивее:const observer = new IntersectionObserver(handleIntersection, {
root: null, // отслеживаем пересечение с вьюпортом, а не с элементом, поэтому null
threshold: 1 // порог видимости, при котором сработает обзёрвер; 1 означает полную видимость, 0.5 означало бы 50% видимости
});
observer.observe(document.getElementById('target'));
function handleIntersection(entries) {
// Обзёрвер срабатывает в том числе когда элемент скрывается из вьюпорта, поэтому нужна дополнительная проверка
if (entries[0].intersectionRatio === 1) {
logBlockView();
}
}
IntersectionObserver
поддерживается в последних версиях Chrome, Edge и Firefox, для остальных браузеров есть полифил (6.6 КБ в минифицированном виде). Подробнее об IntersectionObserver
на MDN.У Эстонии есть собственная дизайн-система — https://brand.estonia.ee/
А ребята из http://gov.design теперь пилят единый навигатор по государственным сайтам и услугам — https://gov.gosuslugi.ru/
На собеседованиях иногда просят назвать способы отправки запроса на сервер. Помимо очевидных fetch/XMLHttpRequest и прочих джаваскриптовых штук есть более экзотические способы вроде
Вчера узнал о ещё более экзотическом и извращённом способе отправки запроса на сервер с помощью CSS:
Этот способ может использоваться для аналитики и трекинга пользователей, у которых отключен JS. Можно отследить клики по ссылкам, ввод текста в инпуты, клики по чекбоксам, длительность ховера на каком-либо элементе; также можно приблизительно определить браузер и операционную систему пользователя. Подробности — https://github.com/jbtronics/CrookedStyleSheets
Защититься от этого можно только отключив CSS. Параноикам пора переходить на текстовые браузеры :–)
<img src="...">
.Вчера узнал о ещё более экзотическом и извращённом способе отправки запроса на сервер с помощью CSS:
body::after {
content: url('...');
}
Этот способ может использоваться для аналитики и трекинга пользователей, у которых отключен JS. Можно отследить клики по ссылкам, ввод текста в инпуты, клики по чекбоксам, длительность ховера на каком-либо элементе; также можно приблизительно определить браузер и операционную систему пользователя. Подробности — https://github.com/jbtronics/CrookedStyleSheets
Защититься от этого можно только отключив CSS. Параноикам пора переходить на текстовые браузеры :–)
GitHub
GitHub - jbtronics/CrookedStyleSheets: Webpage tracking only using CSS (and no JS)
Webpage tracking only using CSS (and no JS). Contribute to jbtronics/CrookedStyleSheets development by creating an account on GitHub.
У TC39 (технический комитет, разрабатывающий стандарт ECMAScript) появился логотип — https://github.com/tc39/logo
Главной целью был отказ от Эгеи (движок для ведения блога) и переход на что-то попроще. В итоге пока что использую Jekyll, дальше будет видно, насколько с ним будет удобно жить. Главное — теперь нет стороннего кода и всё под моим контролем, есть простор для кастомизации и экспериментов.
Позавчера был мой последний рабочий день в Авито. За год удалось здорово прокачаться во фронтенде, запилить с нуля новый раздел помощи (support.avito.ru) и интегрировать его в мобильные приложения через вебвью, повлиять на развитие общей библиотеки компонентов и нового фронтенд-стека.
Главный вывод, который я сделал — очень многое в работе зависит от команды, это особенно заметно в больших компаниях вроде Авито. Чем сплочённее команда, чем больше в ней единомышленников, тем лучше результат; такой команде не требуется авторитарное управление и навязывание процессов вроде скрама. Если же собрана не очень дружная команда, участники которой не понимают друг друга, результат будет практически нулевым, а попытки навязать команде какие-то процессы скорее всего деморализуют участников и приведут к распаду.
Главный вывод, который я сделал — очень многое в работе зависит от команды, это особенно заметно в больших компаниях вроде Авито. Чем сплочённее команда, чем больше в ней единомышленников, тем лучше результат; такой команде не требуется авторитарное управление и навязывание процессов вроде скрама. Если же собрана не очень дружная команда, участники которой не понимают друг друга, результат будет практически нулевым, а попытки навязать команде какие-то процессы скорее всего деморализуют участников и приведут к распаду.
Обратил внимание на UX установщиков программ на винде: установщик весит всего несколько сотен килобайт и скачивается практически моментально, чтобы пользователь сразу открыл его и запустил установку. А скачивание самой программы сделано частью процесса установки, к длительности которого пользователи уже менее требовательны — раз устанавливается, можно подождать.
TL; DR к статье https://www.viget.com/articles/make-your-site-faster-with-preconnect-hints
Прежде чем обратиться к какому-то ресурсу, браузеру нужно установить соединение: определить IP-адрес хоста и провести TCP/TLS-рукопожатия. При плохих условиях на это могут уйти сотни миллисекунд.
На страницах сайта могут использоваться ресурсы с внешних хостов, например, шрифты с Google Fonts или видео с YouTube. Эти ресурсы чаще всего загружаются отложенно: шрифты начинают загружаться после их обнаружения в таблице стилей, превью для видео с ютуба грузится после инициализации плеера. Чтобы сократить время загрузки этих ресурсов, можно указать браузеру, с каких хостов вы собираетесь загружать ресурсы, и он заранее установит соединения с этими хостами. Если вы используете шрифты с Google Fonts, пропишите в
Атрибут
Если на странице есть плеер ютуба, пропишите в
С тем же успехом можно добавлять подсказки и для других хостов.
Прежде чем обратиться к какому-то ресурсу, браузеру нужно установить соединение: определить IP-адрес хоста и провести TCP/TLS-рукопожатия. При плохих условиях на это могут уйти сотни миллисекунд.
На страницах сайта могут использоваться ресурсы с внешних хостов, например, шрифты с Google Fonts или видео с YouTube. Эти ресурсы чаще всего загружаются отложенно: шрифты начинают загружаться после их обнаружения в таблице стилей, превью для видео с ютуба грузится после инициализации плеера. Чтобы сократить время загрузки этих ресурсов, можно указать браузеру, с каких хостов вы собираетесь загружать ресурсы, и он заранее установит соединения с этими хостами. Если вы используете шрифты с Google Fonts, пропишите в
<head>
такую строчку:<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Атрибут
crossorigin
требуется именно для загрузки шрифтов (https://www.w3.org/TR/css-fonts-3/#font-fetching-requirements).Если на странице есть плеер ютуба, пропишите в
<head>
предыдущую подсказку (плеер использует Roboto с Google Fonts) и ещё четыре подсказки:<link rel="preconnect" href="https://www.youtube.com">
<link rel="preconnect" href="https://i.ytimg.com">
<link rel="preconnect" href="https://i9.ytimg.com">
<link rel="preconnect" href="https://s.ytimg.com">
С тем же успехом можно добавлять подсказки и для других хостов.
https://www.viget.com
Make Your Site Faster with Preconnect Hints | Viget
With preconnect hints, you can reduce request latency and make your site faster.
Почему в CSS не будет селекторов, зависящих от текущего состояния раскладки?
Удобно было бы иметь псевдоклассы вроде
Подробнее — https://wiki.csswg.org/faq#selectors-that-depend-on-layout
Удобно было бы иметь псевдоклассы вроде
:stuck
для элементов с position: sticky
или :overflowing
для элементов, переполненных содержимым. К сожалению, таких псевдоклассов не будет, потому что они могут привести к цикличности — для них можно прописать правила, которые отменят действие этих псевдоклассов:aside { position: sticky; top: 0; }
aside:stuck { position: static; }
Подробнее — https://wiki.csswg.org/faq#selectors-that-depend-on-layout
Постоянно выходят какие-то реакт-подобные библиотеки, которые супербыстрые, работают в IE8 и весят совсем мало. Ничего кардинально нового они не несут, так что вместо них расскажу о действительно интересной библиотеке.
Glimmer — бывший UI-движок Ember, выросший в отдельный проект. Он отличается от реакта и подобных библиотек тем, что его шаблоны компилируются не в JavaScript, а в JSON. Этот JSON на стороне клиента компилируется в байткод, исполняемый в виртуальной машине Glimmer (в терминах Glimmer это называется last mile compilation). Выглядит этот JSON примерно так:
Чем компиляция шаблонов в JSON лучше компиляции в JavaScript? Временем их парсинга, которое критично на мобильных устройствах. Грамматика JSON сильно проще JS, поэтому и парсится JSON гораздо быстрее.
Несмотря на скорость парсинга JSON, с ростом количества шаблонов растут и затраты на их парсинг. Ребята из LinkedIn знатно упоролись и решили свести эти затраты к нулю: вместо компиляции в JSON они сразу компилируют шаблоны в байткод и доставляют их в браузер в бинарном формате, так что на стороне клиента last mile compilation не требуется и виртуальная машина Glimmer может сразу исполнять полученный байткод.
Байткод в бинарном формате сокращает не только время парсинга, но и размер шаблонов. А в ближайшем будущем можно будет добиться ещё большей скорости, портировав части виртуальной машины Glimmer на WebAssembly.
Glimmer — бывший UI-движок Ember, выросший в отдельный проект. Он отличается от реакта и подобных библиотек тем, что его шаблоны компилируются не в JavaScript, а в JSON. Этот JSON на стороне клиента компилируется в байткод, исполняемый в виртуальной машине Glimmer (в терминах Glimmer это называется last mile compilation). Выглядит этот JSON примерно так:
[
['startProgram', [0, []]],
['text', [0, 3]],
['mustache', [1, 3]],
['openElement', [2, 3, 0, []]],
['closeElement', [2, 3]],
['endProgram', [0]]
]
Чем компиляция шаблонов в JSON лучше компиляции в JavaScript? Временем их парсинга, которое критично на мобильных устройствах. Грамматика JSON сильно проще JS, поэтому и парсится JSON гораздо быстрее.
Несмотря на скорость парсинга JSON, с ростом количества шаблонов растут и затраты на их парсинг. Ребята из LinkedIn знатно упоролись и решили свести эти затраты к нулю: вместо компиляции в JSON они сразу компилируют шаблоны в байткод и доставляют их в браузер в бинарном формате, так что на стороне клиента last mile compilation не требуется и виртуальная машина Glimmer может сразу исполнять полученный байткод.
Байткод в бинарном формате сокращает не только время парсинга, но и размер шаблонов. А в ближайшем будущем можно будет добиться ещё большей скорости, портировав части виртуальной машины Glimmer на WebAssembly.
Linkedin
The Glimmer Binary Experience
TIP: если у вас, как и у меня, заблокирован LinkedIn, просто откройте Opera, включите встроенный VPN и злорадно смейтесь над Роскомнадзором (или кто там цензурой занимается).