fa
Feedback
Frontender's notes [ru]

Frontender's notes [ru]

رفتن به کانال در Telegram

Ведущий канал о современном фронтенде: статьи, новости, практики, вайбкодинг и автоматизация фронта ИИ-агентами. Личный блог автора - @just_genych По вопросам рекламы или разработки - @g_abashkin

نمایش بیشتر

📈 تحلیل کانال تلگرام Frontender's notes [ru]

کانال Frontender's notes [ru] (@frontendnoteschannel_ru) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 31 991 مشترک است و جایگاه 4 125 را در دسته فناوری و برنامه‌ها و رتبه 20 191 را در منطقه روسيا دارد.

📊 شاخص‌های مخاطب و پویایی

از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 31 991 مشترک جذب کرده است.

بر اساس آخرین داده‌ها در تاریخ 20 ژوئیه, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -409 و در ۲۴ ساعت گذشته برابر -19 بوده و همچنان دسترسی گسترده‌ای حفظ شده است.

  • وضعیت تأیید: تأیید نشده
  • نرخ تعامل (ER): میانگین تعامل مخاطب 6.91% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 4.96% واکنش نسبت به کل مشترکان کسب می‌کند.
  • دسترسی پست‌ها: هر پست به طور میانگین 2 212 بازدید دریافت می‌کند. در اولین روز معمولاً 1 588 بازدید جمع‌آوری می‌شود.
  • واکنش‌ها و تعامل: مخاطبان به‌طور فعال حمایت می‌کنند؛ میانگین واکنش به هر پست 5 است.
  • علایق موضوعی: محتوا بر موضوعات کلیدی مانند браузер, api, css, интерфейс, загрузка تمرکز دارد.

📝 توضیح و سیاست محتوایی

نویسنده این فضا را محل بیان دیدگاه‌های شخصی توصیف می‌کند:
Ведущий канал о современном фронтенде: статьи, новости, практики, вайбкодинг и автоматизация фронта ИИ-агентами. Личный блог автора - @just_genych По вопросам рекламы или разработки - @g_abashkin

به لطف به‌روزرسانی‌های پرتکرار (آخرین داده در تاریخ 21 ژوئیه, 2026)، کانال همواره به‌روز و دارای دسترسی بالاست. تحلیل‌ها نشان می‌دهد مخاطبان به‌طور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامه‌ها تبدیل کرده‌اند.

31 991
مشترکین
-1924 ساعت
-897 روز
-40930 روز
جذب مشترکین
ژوئیه '26
ژوئیه '26
+37
در 5 کانال‌ها
ژوئن '26
+111
در 0 کانال‌ها
Get PRO
مه '26
+239
در 22 کانال‌ها
Get PRO
آوریل '26
+300
در 0 کانال‌ها
Get PRO
مارس '26
+136
در 1 کانال‌ها
Get PRO
فوریه '26
+156
در 1 کانال‌ها
Get PRO
ژانویه '26
+250
در 60 کانال‌ها
Get PRO
دسامبر '25
+319
در 28 کانال‌ها
Get PRO
نوامبر '25
+379
در 69 کانال‌ها
Get PRO
اکتبر '25
+210
در 32 کانال‌ها
Get PRO
سپتامبر '25
+265
در 90 کانال‌ها
Get PRO
اوت '25
+111
در 6 کانال‌ها
Get PRO
ژوئیه '25
+223
در 2 کانال‌ها
Get PRO
ژوئن '25
+247
در 9 کانال‌ها
Get PRO
مه '25
+255
در 4 کانال‌ها
Get PRO
آوریل '25
+266
در 1 کانال‌ها
Get PRO
مارس '25
+285
در 24 کانال‌ها
Get PRO
فوریه '25
+449
در 27 کانال‌ها
Get PRO
ژانویه '25
+380
در 36 کانال‌ها
Get PRO
دسامبر '24
+612
در 53 کانال‌ها
Get PRO
نوامبر '24
+576
در 40 کانال‌ها
Get PRO
اکتبر '24
+439
در 27 کانال‌ها
Get PRO
سپتامبر '24
+470
در 34 کانال‌ها
Get PRO
اوت '24
+466
در 24 کانال‌ها
Get PRO
ژوئیه '24
+458
در 34 کانال‌ها
Get PRO
ژوئن '24
+431
در 33 کانال‌ها
Get PRO
مه '24
+442
در 30 کانال‌ها
Get PRO
آوریل '24
+371
در 26 کانال‌ها
Get PRO
مارس '24
+374
در 13 کانال‌ها
Get PRO
فوریه '24
+846
در 4 کانال‌ها
Get PRO
ژانویه '24
+590
در 22 کانال‌ها
Get PRO
دسامبر '23
+786
در 34 کانال‌ها
Get PRO
نوامبر '23
+431
در 8 کانال‌ها
Get PRO
اکتبر '23
+522
در 1 کانال‌ها
Get PRO
سپتامبر '23
+842
در 0 کانال‌ها
Get PRO
اوت '23
+1 001
در 0 کانال‌ها
Get PRO
ژوئیه '23
+1 476
در 0 کانال‌ها
Get PRO
ژوئن '23
+1 096
در 0 کانال‌ها
Get PRO
مه '23
+916
در 0 کانال‌ها
Get PRO
آوریل '23
+908
در 0 کانال‌ها
Get PRO
مارس '23
+878
در 0 کانال‌ها
Get PRO
فوریه '23
+584
در 0 کانال‌ها
Get PRO
ژانویه '23
+1 454
در 0 کانال‌ها
Get PRO
دسامبر '22
+638
در 0 کانال‌ها
Get PRO
نوامبر '22
+1 656
در 0 کانال‌ها
Get PRO
اکتبر '22
+536
در 0 کانال‌ها
Get PRO
سپتامبر '22
+537
در 0 کانال‌ها
Get PRO
اوت '22
+857
در 0 کانال‌ها
Get PRO
ژوئیه '22
+1 735
در 0 کانال‌ها
Get PRO
ژوئن '22
+523
در 0 کانال‌ها
Get PRO
مه '22
+218
در 0 کانال‌ها
Get PRO
آوریل '22
+268
در 0 کانال‌ها
Get PRO
مارس '22
+186
در 0 کانال‌ها
Get PRO
فوریه '22
+424
در 0 کانال‌ها
Get PRO
ژانویه '22
+734
در 0 کانال‌ها
Get PRO
دسامبر '21
+816
در 0 کانال‌ها
Get PRO
نوامبر '21
+663
در 0 کانال‌ها
Get PRO
اکتبر '21
+1 410
در 0 کانال‌ها
Get PRO
سپتامبر '21
+565
در 0 کانال‌ها
Get PRO
اوت '21
+1 525
در 0 کانال‌ها
Get PRO
ژوئیه '21
+1 531
در 0 کانال‌ها
Get PRO
ژوئن '21
+1 533
در 0 کانال‌ها
Get PRO
مه '21
+2 084
در 0 کانال‌ها
Get PRO
آوریل '21
+1 811
در 0 کانال‌ها
Get PRO
مارس '21
+8 672
در 0 کانال‌ها
Get PRO
فوریه '21
+1 828
در 0 کانال‌ها
Get PRO
ژانویه '21
+1 309
در 0 کانال‌ها
Get PRO
دسامبر '20
+12 495
در 0 کانال‌ها
تاریخ
رشد مشترکین
اشارات
کانال‌ها
21 ژوئیه+3
20 ژوئیه+2
19 ژوئیه0
18 ژوئیه+2
17 ژوئیه+4
16 ژوئیه+3
15 ژوئیه+2
14 ژوئیه+2
13 ژوئیه+1
12 ژوئیه0
11 ژوئیه+1
10 ژوئیه+2
09 ژوئیه+2
08 ژوئیه0
07 ژوئیه+2
06 ژوئیه+2
05 ژوئیه+2
04 ژوئیه+3
03 ژوئیه+4
02 ژوئیه0
01 ژوئیه0
پست‌های کانال
В июле снова видно, как digital и IT окончательно уходят от «просто контента» к системе, где решают скорость, ИИ и нормальная упаковка смысла. Кто раньше выстраивает понятную подачу и сильную экспертность, тот и забирает внимание рынка. Если вы работаете в digital или IT, сейчас особенно важно не писать «как все» а говорить так, чтобы вас хотелось читать, сохранять и передавать дальше. Мы как раз собрали в этой папке материалы, которые помогают делать это без лишней воды. Здесь готовим большое SMM исследование в сфере промышленности, где покажем, как меняется работа с контентом, в какую сторону идти, и что прямо сейчас в ТОПе. Отдельно здесь про управление ИТ и цифровой трансформацией. Папка подойдет тем, кто: • продвигает digital- и IT-проекты; • собирает сильную упаковку для экспертов и компаний; • хочет говорить с аудиторией современно и по-человечески. Сохранить папку себе 🗂

2
Как вытащить типы из Strapi-популейта на уровне компилятора В Strapi есть засада: ответ от запроса меняет форму в зависимости
Как вытащить типы из Strapi-популейта на уровне компилятора В Strapi есть засада: ответ от запроса меняет форму в зависимости от того, что ты в него сунул. Дергаешь статью без populate — получаешь только плоские поля. Кидаешь populate: { category: true } — категория уже внутри. А если еще и fields: ['name'] туда добавить, то категория придет урезанной. Итог: один эндпоинт выдает кучу разных вариантов, и статический TypeScript-интерфейс это никак не разрулит. Он либо нагло врет — обещает поля, которых в реальности нет, либо тупо сливается в any. В статье показывают, как забить на эту проблему с помощью кодогенерации: вытаскиваешь схему из живого Strapi, генеришь по ней TypeScript-клиент, и самое мясо — заставляешь систему типов выводить ответ прямо из аргумента populate еще до компиляции. Типа как в Prisma: какой тип вернется, зависит от того, что ты передал в метод. Все на TypeScript, клиент open-source под MIT, ссылка внизу. Почитать на Habr 👉 Frontender's notes
1 683
3
Как React-магазину не обрасти левыми зависимостями? Вот классика: засунули карту банковской карты в entities/card/ui — туда п
Как React-магазину не обрасти левыми зависимостями? Вот классика: засунули карту банковской карты в entities/card/ui — туда попали маска номера, баланс и статус. Прошло два спринта, и в карточку влепили «заблокировать карту» и «изменить лимит». В итоге entity начала тащить features/block-card, features/change-card-limit, а ещё проверку прав мимо public API. Когда эту карточку воткнули в выбор счёта списания, с ней припёрлись лишние зависимости и проверки ролей. Никто не пострадал, но на фикс ушло время. В entity оставили только чистый CardPreview, сценарии подняли уровнем выше, композицию дашборда переложили в widgets/card-summary, потом заново прогнали ролевые тесты. На ревью до названия папки дошли только в конце. Сначала обсуждали другое: какие будущие изменения эта граница позволит оставить без выноса за пределы. В FSD 2.1 советуют начинать со страниц и вытаскивать код ниже, когда появляется переиспользование. Это норм дефолт, хотя, если рядом есть второй похожий потребитель, границу иногда можно резать раньше. Детали тут: https://habr.com/ru/articles/1060256/ 👉 Frontender's notes
1 750
4
Гугл тебя кормит, гугл тебя поит. Даже целую аналитическую систему можно соорудить, не вынимая кошелька Собираешь ответы чере
Гугл тебя кормит, гугл тебя поит. Даже целую аналитическую систему можно соорудить, не вынимая кошелька Собираешь ответы через формы, вешаешь визуализацию на сайт — и, как только набирается нужная цифра, автоматом улетает письмо. Авторы в качестве демки обкатали это на исследовании туристических предпочтений. Жми, всё расписано. Читать далее 👉 Frontender's notes
1 759
5
⁣Типизация и детерминированная обработка состояния скролла при виртуализации списков с IntersectionObserver и кастомным Suspense в React 19 IntersectionObserver на бесконечных списках часто порождает гонки: элемент пересек границу, запрос ушел, а пользователь улетел скроллом дальше. Результат — повторные вызовы API и пустые мертвые зоны в рендере. В React 19 это решается через Suspense и хук use, делая обработку скролла детерминированной. Замкнутое состояние скролла Вместо разрозненных useState для startIndex и endIndex используем явный интерфейс ScrollState. Он обновляется атомарно — нельзя изменить один индекс без другого. Это исключает рассинхрон и гарантирует, что стейт всегда консистентен при передаче в Suspense-зависимый компонент. interface ScrollState { startIndex: number; endIndex: number; } Синхронизация через Suspense и use Когда IntersectionObserver срабатывает, мы сетим новый ScrollState. Компонент ItemsLoader внутри Suspense использует use(fetchItems(scrollState)) — это приостанавливает рендер до разрешения промиса. Наблюдатель пересоздается только в useEffect, который зависит от state.endIndex, то есть после того, как предыдущий диапазон гарантированно зафиксирован в DOM. Типичная ошибка и trade-off Ошибка: пытаться блокировать скролл флагами isFetching или отключать observer вручную. Это ломает UX и не решает проблему гонок, так как флаг может быть false до завершения ререндера. Минус подхода — он ломает классический поток «эффект -> стейт -> ререндер», требуя отказа от кастомных useEffect-решений. Но плюс — полная детерминированность: новые данные грузятся только после рендера старых. Практический совет Для production убедись, что fetchItems внутри use возвращает не просто массив, а структуру с totalCount или hasMore — это позволяет корректно остановить наблюдение при достижении конца списка. Иначе observer будет срабатывать на последнем sentinel-элементе бесконечно. Вывод: Замыкание скролл-состояния в атомарный interface и ожидание рендера через Suspense устраняет гонки IntersectionObserver без костылей, делая поведение списка полностью предсказуемым для пользователя и инженера.
1 633
6
Pete Hunt снова в деле — теперь будет рулить Next.js Гильермо Раух запостил в X: Vercel подтянул Пита Ханта и Ника Шрока (тог
Pete Hunt снова в деле — теперь будет рулить Next.js Гильермо Раух запостил в X: Vercel подтянул Пита Ханта и Ника Шрока (того самого, что придумал GraphQL). Пит — один из тех старых волков, что стояли у истоков React, теперь он возглавит Next.js. Ещё Vercel наконец-то вводит регулярный ежемесячный график security-релизов для Next.js — первый такой выйдет уже через пару дней. → Читать подробнее Cloudflare переписал блог на EmDash Cloudflare взял и перекроил свой блог целиком на EmDash — это их «духовный наследник WordPress» на Astro. Анонсировали они это, кстати, 1 апреля, но без шуток. Linaria: создатель объясняет, зачем городил новое «Runtime CSS-in-JS — всё, приплыли», — заявляет мейнтейнер Linaria. Теперь он наваял dx-styles, zero-runtime альтернативу, которая всё жует на этапе сборки. Гайд по миграции с Linaria уже есть. ReactBench: кодинг-агентов проверяют на React-коде Команда React Scan и Million.js запилила eval для coding-агентов на «реалистичной React-работе». Задача — отсеять модели, которые блистают в других бенчмарках, но тупят на нормальном React-коде. Пока лидирует GPT 5.6 Sol. → Подробнее React Native Skia 2.9 — выкатили Вышла свежая версия библиотеки для 2D-графики под React Native. shadcn/typeset: полная типографика для HTML Готовая типографская система для обработанного HTML (ну, там вывод Markdown) — один CSS-файл и один класс-обёртка. Настраивается парой CSS-переменных. Есть конструктор, если хочешь заморочиться. И ещё: — EmDash — опенсорс от Cloudflare — shadcn/typeset на GitHub — Preact 11.0 Beta 2 — «одна из последних бет» — react-dropzone 17.0 — React Mosaic 7.0 — TanStack: график популярности npm-пакетов 👉 Frontender's notes
1 519
7
Ищем новичков во frontend-разработке и вёрстке сайтов. Айтилогия запускает бесплатное обучение, где будет: 1. Практика на реа
Ищем новичков во frontend-разработке и вёрстке сайтов. Айтилогия запускает бесплатное обучение, где будет: 1. Практика на реальном заказе ценой до 10 000₽. 2. Разбор работ куратором. 3. Задачи от Fullstack-разработчика с 12-летним опытом. 4. Именной сертификат. И главное — ты почувствуешь уверенность. Потому что увидишь, что выполнить заказ на frontend-проект тебе по силам. 👉 Приходи на бесплатное обучение и зови с собой друзей 🔥 С 2019 Айтилогия стабильно помогает с обучением, практикой, зарабатывать на фрилансе и проходить собеседования.
1 394
8
Как скрестить Symfony 8 с Angular 22? Ровно с этого вопроса я и стартанул, когда полез разбираться во всю эту кашу. Но после
Как скрестить Symfony 8 с Angular 22? Ровно с этого вопроса я и стартанул, когда полез разбираться во всю эту кашу. Но после того как разгреб, могу смело заявить: норм тема, рабочая, и поддерживать такую архитектуру без геморроя вполне реально. В посте — детальное описание того, как замутить веб‑приложение с удобной обвязкой из Docker контейнеров. CI/CD тут даже не упоминается — всё чисто про дев-сторону процесса разработки. Автор пилит это всё в PHPStorm 2026.1.4 от Jetbrains, но вообще IDE — до лампочки. Теоретически можно даже в блокноте наваять приличный код. Читать далее 👉 Frontender's notes
1 652
9
⁣Типизация и детерминированная обработка race condition при конкурентной записи в WebSocket через AbortController и AsyncQueue в React 19 Race condition в WebSocket-соединениях — не просто теоретическая проблема. В production она возникает, когда несколько компонентов одновременно пытаются отправить данные: два сабмита формы, два useEffect с разными контекстами. Сообщения перемешиваются, теряются, или соединение падает с нечитаемым traceback. Стандартный WebSocket не гарантирует порядок, если не управлять очередью вручную. Почему это важно для React 19 React 19 не предоставляет магического решения для WebSocket. useCallback и AbortController — стандартные API, работающие с React 16, но в 19-й версии они стабильны, и связка с очередью чувствует себя уверенно. Однако race condition остаётся: два вызова send из разных компонентов без синхронизации приводят к хаосу. Решение: AsyncQueue и AbortController Берём самописный AsyncQueue с FIFO и AbortController для отмены устаревших задач. Очередь гарантирует, что следующее сообщение отправится только после получения ответа на предыдущее. AbortSignal позволяет скипать задачу, если компонент размонтировался или пользователь передумал. Вот типизированный пример: type SendTask = { data: unknown; signal: AbortSignal; }; class AsyncQueue { private queue: SendTask[] = []; private processing = false; async enqueue(task: SendTask): Promise<void> { this.queue.push(task); if (!this.processing) { this.processing = true; while (this.queue.length > 0) { const current = this.queue.shift()!; if (current.signal.aborted) continue; await this.sendToWS(current.data); } this.processing = false; } } private async sendToWS(data: unknown): Promise<void> { await new Promise<void>((resolve, reject) => { const timeout = setTimeout(() => reject(new Error('Timeout')), 5000); ws.send(JSON.stringify(data)); ws.once('message', () => { clearTimeout(timeout); resolve(); }); }); } } const useSafeWS = () => { const queueRef = useRef(new AsyncQueue()); const send = useCallback((data: unknown, signal?: AbortSignal) => { const controller = new AbortController(); const effectiveSignal = signal || controller.signal; queueRef.current.enqueue({ data, signal: effectiveSignal }); if (!signal) controller.abort(); }, []); return { send }; }; Типичная ошибка: игнорирование таймаутов и очистки Главный подводный камень — если сокет завис на ожидании ответа, вся очередь блокируется. В production добавьте fallback на переподключение: при таймауте разрывайте соединение, очищайте очередь и инициируйте reconnect. Без этого компоненты будут ждать вечно, а состояние интерфейса застынет. Trade-off: самописное vs библиотечное решение Самописная очередь требует тестирования edge cases: таймауты, параллельные подключения, отмена задач. Библиотеки вроде ws-queue решают это из коробки, но добавляют зависимость и скрывают логику. Я выбираю своё — прозрачность дебага и ноль зависимостей. Минус: нужно покрыть тестами сценарии с зависанием и переподключением. Вывод: Race condition в WebSocket решается через FIFO-очередь с AbortController, но не забывайте про таймауты и fallback на reconnect, иначе детерминизм превратится в блокировку.
1 537
10
Ты не шаришь в CSS: вопросы и ответы, апдейт 2026 Автор канала продолжает свою рубрику и наваял новый пост про CSS. До этого
Ты не шаришь в CSS: вопросы и ответы, апдейт 2026 Автор канала продолжает свою рубрику и наваял новый пост про CSS. До этого похожий текст про HTML залетел в топ и стал одним из самых популярных за последнее время. Задача этого опроса — просто развлечь народ. Вопросы заточены под реальную работу, но сходу на них ответит не каждый. Не знаешь половину — пофиг, ничего страшного. Почитать 👉 Frontender's notes
1 818
11
Фрактальный интерфейс для софта — звучит как бред, но есть нюанс Кто-то предложил сделать интерфейсы в программах фрактальным
Фрактальный интерфейс для софта — звучит как бред, но есть нюанс Кто-то предложил сделать интерфейсы в программах фрактальными. Идея в том, что такая штука подстраивается под мозги конкретного юзера и не лезет в его личное пространство. Приложение при этом работает как живой организм — само развивается вместе с пользователем, а не тупо стоит на месте. Читать далее 👉 Frontender's notes
1 958
12
⁣Детерминированный Suspense в React 19: Zero-CLS через типизированный fallback при SSR Layout shift при SSR с Suspense — хроническая боль для CLS и LCP. Классический подход рендерит fallback только на клиенте, вызывая дёрганье UI во время гидрации. React 19 исправляет это через пропс clientOnlyFallback={false}, позволяя серверу вставлять типизированный fallback с фиксированной высотой. Почему это важно При SSR без детерминированного fallback браузер не резервирует место под асинхронный контент. В момент гидрации контент появляется, и CLS улетает в красную зону. Решение — серверный fallback с явно заданными размерами, который не меняется при гидрации. Типизированный fallback с предсказуемой высотой Используйте интерфейс с обязательными height (в пикселях) и placeholder, чтобы браузер зарезервировал место до загрузки данных: interface FallbackProps { height: number; placeholder: string; } function StaticFallback({ height, placeholder }: FallbackProps) { return ( <div style={{ height: ${height}px, opacity: 0.3, background: '#f0f0f0', pointerEvents: 'none' }} aria-hidden="true" > {placeholder} </div> ); } function AsyncComponent() { return ( <Suspense fallback={<StaticFallback height={200} placeholder="Загрузка..." />} clientOnlyFallback={false} > <ActualData /> </Suspense> ); } Типичная ошибка Пропуск height или передача нерелевантной высоты. Если размер fallback'а не совпадёт с реальным контентом, CLS вернётся. Для динамических блоков без фиксированной высоты используйте aspect-ratio CSS-свойство в style или вычисляйте размер через IntersectionObserver на сервере. Production-совет Для карточек, списков и таблиц — резервируйте высоту с запасом 10% от ожидаемой. Для блоков с неизвестным контентом комбинируйте min-height и max-height, чтобы избежать пустоты или наложения. Тестируйте на реальных метриках Lighthouse. Вывод: Типизированный fallback с clientOnlyFallback={false} — минимальный шаг к нулевому CLS в SSR, но требует точного знания размеров контента, иначе trade-off между стабильностью и производительностью.
1 873
13
npm 12, TypeScript 7 и Bun на Rust Выкатили npm 12 — жизненные скрипты теперь по дефолту отрублены. Детали TypeScript 7.0 — н
npm 12, TypeScript 7 и Bun на Rust Выкатили npm 12 — жизненные скрипты теперь по дефолту отрублены. Детали TypeScript 7.0 — наконец-то финальный Go-релиз, который «в 10 раз шустрее». Но полного API пока нет, так что советуют сидеть на 6.0. Релиз Чувак, создавший Bun, расказал, как перетащил рантайм с Zig на Rust — сделал это через Claude Code, потратив ~$165k по ценам API. Rust-версия станет базой для Bun 1.4, выкат ожидается со дня на день. История 👉 Frontender's notes
2 081
14
Виртуальные Scroll-контейнеры Свежий выпуск про штуку под названием ng-virtual-scroll-view. Ранее уже разбирали универсальные
Виртуальные Scroll-контейнеры Свежий выпуск про штуку под названием ng-virtual-scroll-view. Ранее уже разбирали универсальные виртуализированные списки, которые юзали одноосевой виртуальный контейнер для скролла. Теперь же из проекта ng-virtual-list вылупилась двухосевая версия — тот самый ng-virtual-scroll-view. Эта штука дружит с Angular версий с 14 по 22. Глянуть API и примеры использования можно в документации. 👉 Frontender's notes
2 364
15
Кажется, digital снова меняется быстрее, чем мы успеваем это осознать. На днях Amazon Ads встроил кнопку «Добавить в корзину»
Кажется, digital снова меняется быстрее, чем мы успеваем это осознать. На днях Amazon Ads встроил кнопку «Добавить в корзину» прямо в пульт от телевизора. Теперь купить товар можно буквально во время просмотра фильма или сериала — без поиска сайта и переходов. Похоже, борьба за внимание закончилась. Началась борьба за одну кнопку. Такие изменения лучше всего показывают, куда движется рынок. И если работаешь в digital или IT, важно замечать не только громкие новости, но и понимать, какие возможности они открывают. Поэтому мы собрали подборку людей, которые не просто следят за новостями, а первыми разбирают, что действительно изменит рынок. Здесь можно почитать подборки, обзоры, реальные кейсы и идеи, которые помогают смотреть на digital и IT немного шире. Сохранить подборку себе 📨
1 747
16
Если хочешь развиваться в машинном обучении — решать реальные бизнес-задачи или уйти в исследования — в Центральном университ
Если хочешь развиваться в машинном обучении — решать реальные бизнес-задачи или уйти в исследования — в Центральном университете есть магистратура под оба сценария. И на нее можно получить грант до 75%. Места ограничены, дедлайн подачи заявок — 20 августа. «Машинное обучение» — это направление с несколькими форматами и треками. В офлайн-формате (пары по вечерам и в выходные в центре Москвы) можно выбрать один из трех треков: ⚫️Индустриальный — сильная база в ML, современные инструменты, реальные задачи от партнеров ⚫️Научный (AIRI × ЦУ) — сложные модели, исследования, подготовка к аспирантуре и работе в передовых лабораториях ⚫️ML в электронной коммерции × Lamoda — работа с реальными данными Lamoda, применение ML для бизнес-задач и возможность попасть на стажировку в компанию Для тех, кто хочет учиться из любой точки мира, есть онлайн-формат: основной трек и продвинутый — для специалистов с опытом в ML. Это полноценная альтернатива офлайну с теми же преподавателями и курсами. Магистратура в Центральном университете — это 2 года обучения, которое можно совмещать с работой, и диплом государственного образца. Карьерная поддержка начинается еще во время учебы: консультации, тренировочные собеседования и помощь с трудоустройством. Студенты уже в процессе обучения выходят на новые позиции или повышаются в грейде в Яндексе, Авито, Т-Банке и других компаниях. Поступление проходит через грантовый конкурс — это одновременно способ попасть на программу и возможность выиграть финансовую поддержку на все время обучения: грант покрывает до 75% стоимости. В 2026 году доступно 550 грантов на все программы магистратуры. Подробнее о программах и условиях участия в конкурсе — по ссылкам ➡️Офлайн программа ➡️Онлайн программа
1
17
⁣Типизация и детерминированное управление ресурсами через FinalizationRegistry и WeakRef в долгоживущих хуках с Suspense React 19 с Suspense вводит состояние "засыпания" компонента, когда эффекты не запускаются и не очищаются. Это создает риск утечек WebSocket-соединений или Worker'ов, которые разработчики часто пытаются закрыть только через cleanup useEffect, не учитывая этот сценарий. Проблема: useEffect не срабатывает при suspend Когда компонент "засыпает", cleanup не вызывается, и ресурсы висят до размонтирования. Обычная практика с useRef удерживает ссылку, блокируя GC: const wsRef = useRef<WebSocket>(null); wsRef.current = new WebSocket('wss://...'); // cleanup не сработает при suspend return () => wsRef.current?.close(); Ошибка: useRef удерживает сильную ссылку, не позволяя сборщику мусора освободить WebSocket даже при отсутствии эффекта. Решение: типизированный менеджер ресурсов Используем WeakRef (слабая ссылка) + FinalizationRegistry (обратный вызов при GC): type ResourceCleanup = () => void; function createResourceManager<T extends object>( name: string, cleanup: (resource: T) => void ) { const registry = new FinalizationRegistry<ResourceCleanup>( (cleanupFn) => cleanupFn() ); return { register(resource: T) { const ref = new WeakRef(resource); registry.register(resource, () => { const res = ref.deref(); if (res) cleanup(res); }); return ref; }, unregister(resource: T) { registry.unregister(resource); } }; } Применение в хуке с Suspense: const wsManager = createResourceManager('chat-ws', (ws) => ws.close()); function ChatComponent() { const wsRef = useRef<WeakRef<WebSocket> | null>(null); useEffect(() => { const ws = new WebSocket('wss://chat'); wsRef.current = wsManager.register(ws); return () => wsManager.unregister(ws); }, []); } Смысл: WeakRef не блокирует GC, а FinalizationRegistry гарантирует cleanup после удаления объекта. Типизация через ManagedWeakRef<T>: type ManagedWeakRef<T> = { ref: WeakRef<T>; unregister: () => void }; Важное предупреждение FinalizationRegistry не гарантирует вызов — он приблизительный и может не сработать при интенсивной работе GC. Поэтому всегда комбинируй с явным unregister() в cleanup useEffect. Не злоупотребляй WeakRef в каждом хуке — это низкоуровневый инструмент для редких кейсов (долгоживущие стримы, кэши вне React). Вывод: WeakRef и FinalizationRegistry — последний рубеж защиты от утечек при Suspense, но детерминизм достигается только комбинацией с явной очисткой в cleanup, а не надеждой на GC.
1 970
18
Redux никогда не работал в React То есть, серьёзно: взять голый redux и просто заюзать его в реакте не выйдет. Тебе обязатель
Redux никогда не работал в React То есть, серьёзно: взять голый redux и просто заюзать его в реакте не выйдет. Тебе обязательно понадобится какая-то «react-redux» обёртка. И тогда возникает логичный вопрос: на кой хрен тогда петь мантры про «Redux works with any UI layer»? Читать далее 👉 Frontender's notes
2 242
19
О, понеслась. Во все тяжкие, стартанули 🤣 👉 Frontender's notes
О, понеслась. Во все тяжкие, стартанули 🤣 👉 Frontender's notes
2 578
20
⁣Типизация и детерминированное разрешение конфликтов при кэшировании React Server Actions: staleTimes, revalidate и кастомные GC-стратегии Когда видишь staleTimes и revalidate в React Server Actions, первое желание — поставить числа побольше и забыть. Но на production это заканчивается сессионными багами, которые не воспроизводятся локально. Часто разработчики воспринимают эти настройки как магию, а потом ловят stale data, которую не могут объяснить. Типизация как контракт кэша Делай дискриминационное объединение для каждого кеш-слота: type CacheEntry<T> = | { status: 'fresh'; data: T; timestamp: number } | { status: 'stale'; data: T; lastRevalidate: number } | { status: 'invalid' }; Это заставит компилятор проверить статус перед использованием данных. Никаких runtime-сюрпризов с невалидными записями. Типизируй staleTimes как контракт, а не таймер: type StaleConfig = { maxAge: number; // время свежести данных staleWhileRevalidate: number; // окно показа старых с перезапросом gcAfter?: number; // принудительная чистка }; Кастомная GC-стратегия для долгоживущих данных Для профиля пользователя: maxAge — 10 минут, staleWhileRevalidate — 1 час, gcAfter — 2 часа. Полный sweep убивает производительность. Используй вероятностное удаление: function gcSweep(cache: Map<string, CacheEntry<unknown>>, config: StaleConfig) { const now = Date.now(); for (const [key, entry] of cache) { if (entry.status === 'invalid' || (entry.timestamp + config.gcAfter! < now && Math.random() < 0.1)) { cache.delete(key); } } } Шанс 10% на удаление просроченной записи не даёт GC-взрыва и держит кеш в чистоте без блокировок. Детерминированное разрешение конфликтов Два способа. Первый — deduped fetch с типизированным локом: const lock = new Map<string, Promise<unknown>>(); async function dedupedFetch<T>(key: string, fetcher: () => Promise<T>): Promise<T> { if (!lock.has(key)) { lock.set(key, fetcher().finally(() => lock.delete(key))); } return lock.get(key)!; } Второй — версионность: храни счётчик версий в кеш-слоте, при записи проверяй, что версия не устарела. Это решает гонки при параллельных revalidate. Типичная ошибка: не типизировать состояние кеша и полагаться на runtime-проверки. В production это ведёт к race conditions, которые не видны в dev-режиме с одним пользователем. Строй явный жизненный цикл: через revalidate с проверкой типов решай актуальность данных, а GC делай фоновым и вероятностным. Вывод: Явная типизация состояний кэша, декларативный staleTimes-контракт и вероятностный GC — это не про микрооптимизацию, а про детерминированное управление потоком данных в production-grade приложениях.
2 119