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


Новости

  • вышел релиз pnpm 10.12.1:
    • выкатили экспериментальную поддержку global virtual stores — теперь в node_modules хранятся не сами пакеты, а только симлинки на центральное хранилище в файловой системе, которое может переиспользоваться сразу всеми проектам; поэтому теперь установка пакетов может быть очень быстрой за счёт установленных ранее и закешированных в хранилище пакетов
    • добавили в настройки режим catalogMode для управления установкой пакетов для монореп
  • Node.js 18 уже достигла End-Of-Life, и мигрировать рекомендуется сразу на текущую активную 22 версию, чтобы в следующий раз нескоро переезжать (апрель 2027)
  • выпущен Jest 30:
    • поддерживает .mts и .cts файлы по умолчанию
    • удалили алиасы expect, для миграции добавили eslint-плагин с автофиксером
    • обновили поддержку jsdom, дропнули поддержку Node 14, 16, 19 и 21, TS < 5.4
    • так как Гугл задепрекейтил домен goo.gl, который использовался для хранения снепшотов, то придётся их все переделать
  • для v0 сделали режим Design Mode, чтобы править параметры в UI без залезания в код (пока поддерживается Tailwind и shadcn/ui)
  • в Chromium 138, Firefox 140 и Safari 26 Beta изменится принцип декодирования символов < и > в атрибутах элемента с помощью методов innerHTML и outerHTML
<div data-content="<u>hello</u>"></div>
div.outerHTML;
// раньше было <div data-content="<u>hello</u>"></div>
// теперь будет <div data-content="&lt;u&gt;hello&lt;/u&gt;"></div>
  • вышел Biome v2:
    • линтинг типов теперь не завязан на tsc
    • поддержаны вложенные конфиги
    • для того, чтобы линтинг мог завязываться не только на один файл, выпущен специальный сканер файлов, который находит вложенные конфиги и индексирует файлы
    • появилась первая ограниченная поддержка плагинов и HTML-форматтер
  • в редакторе Zed появился встроенный Debugger (имплементирован Debug Adapter Protocol (DAP))
  • вышла H3 v2 beta: быстрый сервер, который работает в разных райнтаймах (Node.js, Deno, Bun), но при этом основывается на стандартных API вроде RequestResponseURL и Headers

Проекты

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

JS/TS

  • как сейчас дела в React и экосистеме билд-тулов и фреймворков: по скачиваниям Vite-плагин растёт и догоняет Next, а CRA после депрейката расти перестал; среди остальных React-специфичных фреймворков больше всего скачиваний у React Router, а Astro, Expo и Gatsby существенно отстают
  • import-maps изначально не позволяли загружать любые модули до загрузки самого import-map-а, а также всего на страницу мог быть только один import-map: это ограничение усложнило применение технологии у инженеров Shopify и они совместно с вендорами браузеров проработали изменение в спецификации и внедрили в Chromium и WebKit; теперь import-map-ов может быть несколько, и они мерджатся в один, а также любой модуль может загружаться до или после загрузки самого map-а
  • утилитарный тип Prettify, которого пока нет в стандартной поставке TS, улучшает читаемость «сборных» типов:
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
  • юзкейсы top-level await в браузере и Node.js:
    • запрос конфига на старте приложения const config = await fetch('/config.json')
    • динамический импорт другого модуля const dbDriver = await import('./drivers/postgres.js')
    • ожидание инициализации (в момент выполнения top-level await выполнение модуля становится на паузу)
  • обзёрверы в JS (ResizeObserver, MutationObserver…) имеют примерное одинаковое API (и одинаково не очень удобное), поэтому автор предлагает использовать функцию-обёртку, которая принимает DOM-элемент и коллбек на вход, инкапсулирует создание обзёрвера и возвращает функции unobserve и disconnect

CSS

{
color:
color(
from var(--color) xyz
round(up, min(1, max(0, 0.18 - y)))
round(up, min(1, max(0, 0.18 - y)))
round(up, min(1, max(0, 0.18 - y)))
);
}
  • в комбинированных анимациях, где используются scale и translate одновременно, важен порядок написания свойств: если scale писать перед translate, то тогда translate будет выполняться неравномерно, так как scale будет «умножать» значения translate
  • есть такая функция filter() (не путать со свойством filter), которая позволяет создать комбинированный фильтр, например, из градиента и SVG; всё бы хорошо, но она работает только в Safari, а если хочется кроссбраузерно сделать на градиентной картинке, к примеру, зернёный фильтр, то нужно отдельно задать всему блоку свойство filter и градиент наслоить на зерно

HTML

  • чеклист для проверки правильности синтаксиса респонсив-изображений (srcset, sizes) с примерами правильно/неправильно

Платформа

  • квиз с 32 ситуациями, с которыми вы уже сталкивались или ещё столкнётесь в своей карьере фронтендера: выполнение всех пунктов сделает вас почтенным пенсионером разработки