Frontend VK Hub

Frontend VK Hub

Комьюнити VK для фронтендеров. Кто и что стоит за интерфейсами, которыми пользуются миллионы пользователей, — от Почты Mail до VK Teams — рассказываем здесь 🤘

Username
@frontendhubvk
Category
Technologies
Country
RussiaRussia
Created
, 1 year
Subscribers1,115−2 last week
Avg views per post, 7d170−24.6% vs prev 7d
ERR15.20%last 7 days

Subscribers, 30 days

Oct 19 – Nov 4−5 (−0.4%)

Show as table
DateSubscribers
Oct 19, 20261,120
Oct 20, 20261,118
Oct 21, 20261,118
Oct 22, 20261,117
Oct 23, 20261,118
Oct 24, 20261,119
Oct 25, 20261,118
Oct 26, 20261,118
Oct 27, 20261,117
Oct 28, 20261,117
Oct 29, 20261,116
Oct 30, 20261,116
Oct 31, 20261,116
Nov 1, 20261,116
Nov 2, 20261,115
Nov 3, 20261,116
Nov 4, 20261,115

Average views per post by day

By publication day

Show as table
DateAvg views per post
Oct 7, 2026397
Oct 9, 2026390
Oct 13, 2026300
Oct 15, 2026230
Oct 20, 2026234
Oct 22, 2026184
Oct 27, 2026232
Oct 29, 2026170
Nov 3, 2026169

Most viewed this month

  1. 01

    Vite+ — не новая версия Vite и не его замена. Это отдельная утилита, которая объединяет инструменты вокруг Vite в один CLI: Vite 8, Vitest 5, Oxlint, Oxfmt, Rolldown и tsdown. 28 сентября VoidZero выпустила первый стабильный релиз. Разбираемся вместе с Петром Гилевичем, руководителем веб-разработки контентных сервисов ВКонтакте, как там всё устроено. В чём идея Фронтенд-проект требует набор инструментов: сборщик, тесты, линтер, форматтер, сборка npm-пакетов. Каждый обновляется сам по себе, у каждого своя конфигурация, а локальное окружение и CI расходятся — привет, worked on my machine. Заявленные кратные ускорения касаются линтинга и нового ядра сборки в Vite 8. Версии всех инструментов подобраны и протестированы вместе, обновляются одной командой и гарантированно работают в связке. Как устроено Глобальная утилита vp — отдельная программа, ставить через npm не нужно. Она смотрит, какая версия Node.js нужна проекту, скачивает её и переключает при переходе между проектами. В самом проекте вместо отдельных Vite, Vitest и Oxlint в зависимостях остаётся один пакет vite-plus — версии инструментов зашиты в него. Есть нюанс: если доставить какой-то инструмент отдельно, можно случайно получить вторую его копию и сломать связку — документация предупреждает об этом. Vite Task в монорепозитории и кеширование сборки Если вы разрабатываете несколько пакетов в одном репозитории, рутину — прогоны тестов и другие пайплайны — берёт на себя движок Vite Task. Он умеет то, ради чего раньше отдельно ставили Turborepo. Во-первых, он видит, какой пакет от какого зависит, и запускает сборки в правильном порядке: сперва библиотека, потом зависящее от неё приложение. Внутри одной сборки порядок модулей и так определяет сборщик — а вот очерёдность сборок между пакетами одного репозитория как раз зона ответственности Vite Task. Во-вторых, он кеширует сборки: vp run build --cache снимает fingerprint зависимостей модуля. Запустите команду снова, не меняя код, — сборка полностью пропустится, и результат мгновенно вернётся из кеша. Пока кеш хранится локально, но у Vite+ в планах удалённый — как у конкурентов, в том числе для использования на CI. Как Vite+ стал открытым Изначально Vite+ планировали сделать платным. Но до публичного релиза от платной модели отказались: код открыли под MIT. Почему передумали — в секции MIT License на сайте VoidZero прокомментировали: «Мы устали спорить, какие функции должны быть платными и как их ограничивать». Летом 2026 Cloudflare купила VoidZero — инструменты остаются открытыми. Что в итоге Получаем управление всей экосистемой вокруг Vite одной командой: один апгрейд вместо синхронизации пяти инструментов. Из коробки есть миграция: vp migrate пытается влить все конфигурации — линтера, форматтера, тестов — в один vite.config.ts, переписывает скрипты package.json на vp-команды и перед изменениями показывает план. Миграция рассчитана на свежие Vite 8+ и Vitest 4.1+; прехуки на Husky (утилита для Git-хуков) остаются как были — их подключают к Vite+ вручную. Отдельный CLI — знак того, что проект растят как целую экосистему для JS-проектов без привязки к пакетному менеджеру и предустановленному Node. Можно предположить, что дальше мы увидим поддержку других сред выполнения и возможность миграции между ними, но обещаний нет.  Старт мощный: 2,4 млн скачиваний в неделю на начало октября, мейнтейнер с мировым именем. Небольшим проектам, которые уже на Vite, пробовать можно. Крупным, вероятно, надо повременить: недавно Vite сменил ядро сборки на Rolldown, и это был очень серьёзный апдейт.  Непонятно, будут ли подобные обновления в ближайшие год-два. Экспериментальный Bundled Dev Mode может быть причиной новых мажорных изменений — тогда мигрировать придётся не один раз. #frontendvkhub #vite #что_нового

    Photo
    Views397
    Forwards8
    Reactions12
    Comments0
  2. 02

    Frame-sizing в Chrome 154: iframe сам подстраивает высоту под контент Виджет комментариев, форма оплаты или дашборд во фрейме почти всегда упираются в высоту. Хост не знает, сколько места нужно странице внутри, поэтому она меряет себя сама и шлёт размер через postMessage, а родитель ловит сообщение и меняет высоту фрейма. Этот мост каждая команда пишет заново, и пока первое сообщение не пришло, фрейм стоит с фиксированной высотой и прокруткой внутри. Chrome 154, вышедший 22 сентября, справляется без скриптов. Нужны две вещи: CSS-свойство frame-sizing на стороне хоста и метатег с согласием в документе внутри фрейма. .embed { width: 100%; height: 500px; /* для браузеров без поддержки */ } @supports (frame-sizing: content-height) { .embed { height: auto; frame-sizing: content-height; max-height: 80vh; } } Встраиваемая страница должна разрешить это явно, иначе хост её размер не получит: <meta name="responsive-embedded-sizing" content="allow-origins=https://publisher.example"> Решение принимает встраиваемая сторона: в allow-origins через пробел перечисляются домены, которым можно сообщать размер, либо ставится *. Схема работает и для фреймов с другого домена и дополняет frame-ancestors из CSP. Тег должен быть в документе с самого начала, добавить его скриптом после загрузки не выйдет. Кроме content-height, у свойства есть content-width, логические content-inline-size и content-block-size, а также auto, которое оставляет прежнее поведение. Для виджетов, растущих вниз, подходит content-height. Размер браузер берёт после загрузки и дальше за каждым изменением вёрстки не следит. Если содержимое поменялось, например подгрузились новые комментарии, документ сам просит пересчитать размер: if ("requestResize" in window) { window.requestResize(); } Вызывать его лучше после того, как все изменения внесены, а не на каждом шаге, чтобы не уйти в цикл пересчётов. За удобство платят сдвигом вёрстки: фрейм вырастает уже после загрузки встроенной страницы и тянет вниз всё, что под ним, поэтому в первом экране такой виджет ухудшит CLS. Старый мост на postMessage пока выбрасывать рано, потому что в Firefox и Safari поддержки нет. Зато метатег во встраиваемые страницы можно добавлять уже сейчас, а на хосте включать frame-sizing под @supports и оставить прежний код запасным путём. А вы сейчас подгоняете высоту iframe через postMessage или живёте с фиксированной? #frontendvkhub #chrome #css

    Photo
    Views390
    Forwards4
    Reactions10
    Comments0
  3. 03

    No text

    Photoalbum
    Views305
    Forwards5
    Reactions—
    Comments—
  4. 04

    No text

    Photoalbum
    Views304
    Forwards5
    Reactions—
    Comments—
  5. 05

    No text

    Photoalbum
    Views304
    Forwards5
    Reactions—
    Comments—

Latest posts

#388Photo

🔵 Chrome 156: IndexedDB на SQLite и random() в CSS 20 октября вышел Chrome 156. IndexedDB перевели с LevelDB и плоских файлов на SQLite без изменения API. В CSS появилась random(), а загрузку модуля после сетевого сбоя можно повторить через import(). В релиз вошли 353 исправления безопасности, шесть из них критические. 🔵 TypeScript 7.1 Beta: API компилятора и content mappers 20 октября вышла бета TypeScript 7.1 с API typescript/sync и typescript/async для разработчиков инструментов. Плагины content mappers позволяют подключать форматы вроде .vue и .svelte к проверке типов. Для запуска через tsc нужен --runExternalCode. В бенчмарке на mui-docs с --noEmit и четырьмя потоками проверка заняла 11,9 с против 22,2 с в TypeScript 7.0. 🔵 Chrome DevTools: Anchor Positioning и память замыканий 20 октября команда Chrome описала обновления DevTools для Chrome 155 и 156. В Elements появился визуальный редактор position-area, а Memory теперь находит неиспользуемые переменные, которые замыкания удерживают в памяти. Инструмент get_css_styles позволяет AI-агентам читать вычисленные стили и применённые CSS-правила. 🔵 Node.js: десять исправлений безопасности 21 октября вышли патчи 26.12.1, 24.22.1 и 22.23.4. В декодере Brotli закрыли уязвимость: распаковка вредоносных данных через node:zlib могла привести к повреждению памяти и удалённому выполнению кода. Проблема затрагивала все три ветки. 🔵 Safari 27.1: API для складного экрана за флагами 23 октября в Safari 27.1 на iPhone Duo появились экспериментальные Device Posture API и Viewport Segments API. Первый позволяет реагировать на частичный сгиб экрана, второй описывает области по обе стороны сгиба. Оба API доступны за флагами. 🔵 Safari 27.2: финальный релиз и правки Grid Lanes 26 октября вышел Safari 27.2. В кастомном <select> можно стилизовать отображаемое значение через ::field-content без <selectedcontent>. В Grid Lanes свойство flow-tolerance переименовали в fit-tolerance, старое имя временно работает как устаревший алиас. 🔵 Firefox 159: анимации по скроллу и реестры веб-компонентов 27 октября в Firefox 159 включили по умолчанию анимации, привязанные к скроллу. Появились scoped custom element registries: у shadow-дерева может быть свой реестр элементов. Одинаковые имена элементов из разных библиотек в таких реестрах не конфликтуют. 🔵 Next.js: запланирован security-релиз 27 октября команда Next.js анонсировала патчи для семи уязвимостей средней критичности. Релиз запланирован на 3 ноября, затронутые версии и инструкции по обновлению опубликуют вместе с исправлениями. 🔵 Node.js 26: LTS до апреля 2029 года 28 октября Node.js 26.13.0 перевёл ветку 26.x в LTS под именем Lithium. Поддержка продлится до конца апреля 2029 года. При переходе со старых LTS проверьте наличие libatomic в Linux-образах. Статьи от инженеров VK: ➡️ Прежде чем работать с AIDL: разбираемся, как устроен IDL ➡️ От AJAX до React: как мы полностью изменили архитектуру разработки фронтенда ВКонтакте #frontendvkhub #дайджест

Open in Telegram
Views169−35%vs avg
Forwards2
Reactions3
Comments0
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
9 h132
33 h169
  1. Total to date169
#387Photo

overflow: auto clip в Chrome 156: липкая шапка таблицы в обёртке с горизонтальной прокруткой ➡️ Chrome 156 от 20 октября разрешил делать элемент контейнером прокрутки только по одной оси: элемент с overflow: auto clip прокручивается по горизонтали, а по вертикали обрезает содержимое. Раньше браузер заменял clip в паре с auto на hidden, и элемент становился контейнером прокрутки по обеим осям. Теперь getComputedStyle возвращает auto clip, а липкий элемент привязывается к контейнеру прокрутки отдельно по каждой оси. Базовый случай — таблица с липкой шапкой и липкой первой колонкой внутри обёртки с overflow-x: auto. У такой обёртки браузер заменяет overflow-y: visible на auto, и она становится контейнером прокрутки по обеим осям. Шапка с top: 0 липнет к обёртке и уезжает вместе со страницей, потому что по вертикали обёртка не прокручивается. В нашем тесте обёртка была шириной 400 px, таблица — 1 200 px, страница прокручена на 600 px. С overflow-x: auto шапка в Chrome 141, Chrome 156 и Firefox 158 уехала на 500 px за верхний край окна, а с auto clip в Chrome 156 осталась у края. .table-wrap { overflow-x: auto; } @supports named-feature(single-axis-scroll-container) { .table-wrap { overflow: auto clip; } } .table-wrap thead th { position: sticky; top: 0; } .table-wrap :is(th, td):first-child { position: sticky; left: 0; } Почему не @supports (overflow: auto clip)? Все актуальные браузеры принимают это значение, и CSS.supports возвращает true даже в Firefox 158, где поддержки нет. В блоге Chrome советуют named-feature(single-axis-scroll-container), и в нашем тесте это условие выполнилось только в Chrome 156. Без проверки браузеры без поддержки превратят auto clip в auto hidden, и всё, что выходит за нижний край обёртки, обрежется. У clip по второй оси есть побочные эффекты. По этой оси элемент не прокручивается и программно: после scrollTop = 150 свойство по-прежнему возвращает 0, а scrollIntoView прокручивает окно вместо обёртки. Выпадающий список, который выходит за нижний край, обрезается без возможности прокрутки, хотя scrollHeight обёртки показывает полную высоту, 380 px. Во flex-контейнере с flex-direction: column у элемента с overflow: auto clip начинает действовать min-height: auto, минимальная высота по содержимому. В нашем тесте в Chrome 156 такой элемент в контейнере высотой 200 px вырос до 600 px, а в Chrome 141 и Firefox 158 сохранил высоту 200 px. В Safari поддержки тоже нет, и там работает запасной overflow-x: auto. Сам auto clip ставим только на обёртку, которой нужна липкость по двум осям, и только внутри проверки named-feature. Выпадающие списки внутри такой обёртки выносим в верхний слой через popover и привязываем к кнопке через anchor positioning, а flex- и grid-элементам задаём min-height: 0, если clip стоит по вертикали, и min-width: 0, если по горизонтали. А как вы сейчас делаете липкую шапку у широких таблиц? #frontendvkhub #chrome #таблицы

Open in Telegram
Views170−35%vs avg
Forwards2
Reactions4
Comments0
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h145
34 h170
  1. Total to date170
#386Photoalbum
Views235−10%vs avg
Forwards3
Reactions—
Comments—
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h167
34 h194
57 h228
70 h235
  1. Total to date235
#385Photoalbum
Views234−10%vs avg
Forwards3
Reactions—
Comments—
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h167
34 h193
57 h227
70 h234
  1. Total to date234
#384Photoalbum
Views233−11%vs avg
Forwards3
Reactions—
Comments—
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h166
34 h191
57 h226
70 h233
  1. Total to date233
#383Photoalbum
Views226−13%vs avg
Forwards3
Reactions—
Comments—
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h165
34 h189
57 h220
70 h226
  1. Total to date226
#382Photoalbum
Views226−13%vs avg
Forwards3
Reactions—
Comments—
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h165
34 h189
57 h220
70 h226
  1. Total to date226
#381Photoalbum
Views236−10%vs avg
Forwards3
Reactions3
Comments0
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
10 h171
34 h197
57 h230
70 h236
  1. Total to date236
#380Photo

Импорт текста через with { type: 'text' }: что делает браузер и почему в Vite он не работает 🤖 С Chrome 155 от 6 октября текстовый файл можно импортировать как модуль: import tpl from './card.html' with { type: 'text' }. Firefox поддерживает такой импорт с версии 153 от 21 июля, в Safari он есть начиная с Technology Preview 251, а в стабильной версии пока нет. Экспорт default содержит текст файла строкой, так что шаблоны, шейдеры и SVG можно подключать без fetch и без плагина сборщика. Браузер не проверяет MIME-тип ответа. В нашем тесте Chrome 156 и Firefox 158 вернули строкой и .js-файл, и ответы с text/html и application/octet-stream. Байты браузер всегда декодирует как UTF-8: кириллица из файла в cp1251 превращается в символы U+FFFD, а BOM в начале отбрасывается. Запрос уходит в режиме cors с Accept: text/plain,*/*;q=0.5 и Sec-Fetch-Dest: text, поэтому ответу с другого origin нужен заголовок Access-Control-Allow-Origin. Какую директиву CSP проверяет браузер? connect-src: при default-src 'none'; script-src 'self' импорт блокируется, а с добавленным connect-src 'self' проходит. Карта модулей различает записи по паре «URL и тип», поэтому файл, импортированный и как JS, и как текст, загружается дважды. Статический импорт в браузере без поддержки ломает весь модуль. Chromium 141 выдаёт TypeError: "text" is not a valid module type., и код модуля не выполняется. Пока Safari такой импорт не поддерживает, в коде без сборки оставляем динамический импорт с запасным fetch: async function importText(url) { try { return (await import(url, { with: { type: 'text' } })).default; } catch (e) { if (!(e instanceof TypeError)) throw e; const res = await fetch(url); if (!res.ok) throw new Error(`${res.status} ${url}`); return res.text(); } } Перехватываем только TypeError: эту ошибку import() выдаёт при неизвестном типе модуля. Сбой сети тоже даёт TypeError, и тогда fetch запрашивает файл повторно. URL передаём абсолютным, например new URL('./card.html', import.meta.url).href: import() отсчитывает относительный путь от URL модуля, а fetch — от URL документа. В Vite 8.3 атрибут не работает. Известные ему ассеты вроде .txt и .svg он молча превращает в URL: файл меньше 4 KiB становится data URL, остальные уходят в /assets/…. Шаблоны .html, .md и шейдеры Vite разбирает как JS, и сборка падает с MISSING_EXPORT или PARSE_ERROR. esbuild 0.28 и webpack 5.112 учитывают атрибут и встраивают содержимое строкой. TypeScript 7 без declare module '*.txt' выдаёт TS2307 (Cannot find module). В проектах со сборкой синтаксис можно писать уже сейчас, если сборщик его понимает, а для Vite нужен суффикс ?raw или плагин, который переписывает такие импорты на ?raw. Без сборки нативный импорт берём, только когда его поддерживают все целевые браузеры, а до тех пор подключаем файлы через importText. #frontendvkhub #chrome #vite

Open in Telegram
Views184−30%vs avg
Forwards1
Reactions5
Comments0
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
11 h143
32 h174
68 h184
  1. After 24 hours174
  2. Total to date184
#379Photo

JPEG XL вернулся в Chrome: что с ним делать фронтенду У любого большого сервиса есть терабайты старых JPEG, которые никто не трогает. Пережимать их в AVIF жалко: каждое сжатие с потерями добавляет новые артефакты к старым, а оригинал потом не вернуть. Вот они и лежат, и каждый день уезжают к пользователям в исходном весе. JPEG XL умеет перепаковывать JPEG без потерь. Файл становится в среднем на 20% легче, а если понадобится, из него можно собрать исходный JPEG байт в байт: cjxl photo.jpg photo.jxl djxl photo.jxl restored.jpg Если на входе JPEG, cjxl перепаковывает его без потерь по умолчанию — флаги не нужны. Долго от этого было мало толку. Chrome перестал поддерживать  формат в 2023 году, в версии 110, а без самого популярного браузера возиться с JXL никто не хотел. 6 октября Chrome 155 включил JPEG XL обратно, на этот раз с декодером jxl-rs на Rust. 13 октября формат включил и Firefox 158, а Safari поддерживает JXL ещё с версии 17. Правда, «поддерживает» в случае Safari — громко сказано. Он показывает только статичные картинки, без анимации и прогрессивной отрисовки, поэтому большой hero появится целиком и только после полной загрузки. В Edge и Samsung Internet формата нет вовсе, так что без запасного варианта не обойтись: <picture>   <source srcset="/img/hero.jxl" type="image/jxl">   <source srcset="/img/hero.avif" type="image/avif">   <img src="/img/hero.jpg" width="1600" height="900" alt=""> </picture> Здесь важен порядок source. Если JXL стоит первым, Safari выберет его вместо AVIF и покажет hero только после полной загрузки. Для LCP-картинки такой порядок может оказаться хуже, чем AVIF на первом месте, так что оба порядка лучше замерить на реальных страницах, чем гадать. С анимацией решение проще: в JXL через <picture> её не отдаём совсем. Атрибут type не отличает анимацию от статики, поэтому Safari честно выберет файл, который не сможет проиграть. Отдавать формат по заголовку Accept тоже можно, но удовольствие сомнительное. Понадобится Vary: Accept, и кеш CDN раздробится. К тому же браузеры перечисляют форматы в разном порядке. Firefox, например, ставит image/jxl после image/avif, и сервер, который берёт первый тип из списка, разным браузерам отдаст разные форматы. Тем, кто обрабатывает картинки в Node, стоит знать ещё одну деталь: в готовых сборках sharp нет libjxl, а вывод в JXL там помечен как экспериментальный. Проще вызывать cjxl напрямую или переложить конвертацию на CDN. Начинать лучше с архива. Старые JPEG перепаковываем без потерь и отдаём через <picture> с JPEG в запасе: качество не страдает, трафик падает сразу. Для новых картинок JXL стоит сравнить с AVIF на своём контенте. Google и сам советует пробовать оба формата и отмечает, что JPEG XL полезнее всего при высоком качестве и при сжатии без потерь. А у вас старые JPEG так и лежат как есть? #frontendvkhub #jpeg #chrome

Open in Telegram
Views234−10%vs avg
Forwards1
Reactions6
Comments0
Views growthHide views growth

Views growth

Hours after publication

Show as table
Hours after publicationViews
0 h0
1 h99
9 h159
36 h190
54 h226
69 h234
  1. After 1 hour99
  2. Total to date234

All posts

Connections