Пульс веб-платформы 16.05.2025


Новости

  • в Chrome 136 обезопасили хранение истории посещения ссылок: с помощью безобидного селектора :visited с вредоносного сайта можно прочекать вашу историю посещения ссылок, так как она применяется к ссылкам сразу на всех сайтах; теперь же история посещения ссылок будет ограничена только конкретным сайтом, и со стороннего сайта вынуть из CSS её будет нельзя
  • Safari обновился до 18.5: добавили поддержку Declarative Web Push, который работает без Service Worker
  • а в версии Safari Technology Preview допилили функцию contrast-color(), которая для переданного цвета автоматом подбирает контрастный чёрный или белый:
color: contrast-color(purple);
  • в Edge пробуют новое API ARIA Notify с помощью которого можно программно вызвать произнесение сообщения для определённой DOM-ноды скринридером:
document.querySelector("#text-editor").ariaNotify("Selected text is bold");

Проекты

  • chrono — парсер даты из строки на человеческом языке в машиночитаемый формат
chrono.parseDate("An appointment on Sep 12-13");
// Fri Sep 12 2014 12:00:00 GMT-0500 (CDT)
  • void — опенсорсный аналог Cursor (на самом деле ещё один пока ещё бесплатный форк VS Code)
  • svg-to-css — транслятор нечитаемой SVG-формы в более читаемый CSS-синтаксис clip-path: shape()
  • leptos — React-подобный фреймворк на Rust со знакомыми паттернами (реактивные сигналы, подобие JSX, компоненты)
  • basecoatui — shadcn/ui, портированный с React в чистый HTML/CSS
  • eslint-plugin-react-you-might-not-need-an-effect — плагин для ESLint, подсвечивающий лишнее использование useEffect

Статьи, мнения, туториалы

JS/TS

  • эволюция альтернативного минималистичного генератора статических сайтов Nue JS привела к ребредингу в Hyper — также минималистичный, но уже полноценный headless view layer, которым изначально и планировался React, но потом что-то пошло не так
  • если вы не уверены точно, какой будет лог у следующего кода, то есть подробное объяснение о работе промисов:
new Promise((resolve) => {
console.log("Deep");
resolve("12");
}).then((result) => console.log(result));
console.log(25);
  • если ваш проект с JS/TS, JSX/TSX, CSS, у вас нет желания мигрировать на новый ESLint (или же надоело дружить между собой Pretier и ESLint), зато есть желание куда-то съехать, то вот гайдик по переезду на Biome
  • противоречие Rust- и JS-тулингов даёт о себе знать: React Compiler — JS-тула, использует Babel, и не работает с Rust-тулченами типа SWC и OXC
  • пример реализации простой Dependency Inversion в React, когда отделяется слой работы с данными и подтягивается в компонент как зависимость
  • Дэн не унимается и продолжает толкать свою телегу: на этот раз напоминание, что RSC могут рендериться в билд-тайме в статичный HTML вовсе без использования «серверных» функций
  • тонкость работы с контекстом в React: если вынести контекст-провайдер в отдельную обёртку и прокидывать содержимое в него через children, то при изменении стейта внутри этой обёртки можно избавиться от лишних ререндеров children, так как они не меняются (и ещё одна статейка про этот же подход, но с более обширным объяснением)
  • новая книга по основам TS «Total TypeScript Essentials» от Matt Pocock: пока не читал, но одобряю не глядя

CSS

  • как с помощью CSS-анимаций делать простую «ретро»-мультипликацию: когда @keyframes используются буквально по прямому назначению, декорации движутся, показываются и скрываются, а в итоге всё кажется живым
  • реализация схем гитарных аккордов на гридах, фукнции attr(), градиентах и container-queries (Chrome only)
  • так, тут опасная и экспериментальная CSS-магия: берём scroll animations, добавляем новенькие CSS-карусели и вишенкой на торте — scroll snaps: так можно в карусельке реализовать динамическую высоту слайдов в зависимости от скролла (Chrome only)
  • псевдоэлементом ::first-letter можно стилизовать не только обычную букву, но и любой символ, к примеру, emoji:
<li>🍎 <strong>Apple</strong> Text</li>
li::first-letter {
initial-letter: 3;
}
  • тема height: 100% неочевидно работает в CSS из-за двух противоречащих друг другу механизмов: 1) по умолчанию во Flow layout родитель принимает минимально необходимую высоту для показа дочерних элементов; 2) высота ребёнка, заданная в % расчитывается относительно родителя. Поэтому для корректной работы процентной высоты во Flow layout она должна быть выставлена в 100% для всех возможных родителей (#root, body, html). Или же можно не заморачиваться и использовать другой контекст форматирования — Grid layout, в котором не родитель схлопывается под высоту ребёнка, а наоборот дети растягиваются на высоту родителя

Платформа

  • как узнать, используется ли на вашем сервере gzip или другое сжатие: в девтулзах во вкладке Network смотрим на выполненный запрос, в колонке Size сверху отображается transferred size и пониже actual size; если transferred < actual, значит сжатие есть