Telegram Web
Реализация такой обёртки на Реакте
Использование обёртки с Реакт-Роутером (v3)
Ваня Акулов (@iamakulov_channel) справедливо спрашивает, зачем нужна эта обёртка — я не объяснил, в чём проблема.

Представьте, что в футере вашего 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 и прочих джаваскриптовых штук есть более экзотические способы вроде <img src="...">.

Вчера узнал о ещё более экзотическом и извращённом способе отправки запроса на сервер с помощью CSS:


body::after {
content: url('...');
}


Этот способ может использоваться для аналитики и трекинга пользователей, у которых отключен JS. Можно отследить клики по ссылкам, ввод текста в инпуты, клики по чекбоксам, длительность ховера на каком-либо элементе; также можно приблизительно определить браузер и операционную систему пользователя. Подробности — https://github.com/jbtronics/CrookedStyleSheets

Защититься от этого можно только отключив CSS. Параноикам пора переходить на текстовые браузеры :–)
У TC39 (технический комитет, разрабатывающий стандарт ECMAScript) появился логотип — https://github.com/tc39/logo
Как амперсанд эволюционировал из латинского et (тот же «и») в отдельный символ
Шпаргалка по основным командам перемещения и удаления текста в терминале (для тех, кто устал от стрелочек или кому было лень специально это гуглить)
Выкатил очередной редизайн своего сайта: http://andrew-r.ru
Главной целью был отказ от Эгеи (движок для ведения блога) и переход на что-то попроще. В итоге пока что использую 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, пропишите в <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">


С тем же успехом можно добавлять подсказки и для других хостов.
Наглядная демонстрация профита от преконнекта к хосту гуглошрифтов
Почему в CSS не будет селекторов, зависящих от текущего состояния раскладки?

Удобно было бы иметь псевдоклассы вроде :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 примерно так:

[
['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.
TIP: если у вас, как и у меня, заблокирован LinkedIn, просто откройте Opera, включите встроенный VPN и злорадно смейтесь над Роскомнадзором (или кто там цензурой занимается).
2025/07/07 14:15:08
Back to Top
HTML Embed Code: