tgindex
Виталий и Платформа

Виталий и Платформа

Статистика

📍 О том, как всё устроено в веб-платформе и что происходит в индустрии фронтенда ⭐️ Новости, полезные выжимки, находки и напоминания 👨‍💻 Вопросы и предложения @web_platform_support 🔗 juwain.github.io/web-platform

Последний пост
14 авг.
Последнее чтение
19:21
Постов за неделю
1
Всего постов
25
Тип
открытый
Язык
русский
Категория
Новости и СМИ
В каталоге с
13 авг.
Подписчики
1 827
−3 за 3 дн.
Сутки
−1
−0,05%
Неделя
 
Месяц
 
Просмотров на пост
1 544
25 постов
Вовлечённость
84,5%
к подписчикам
Постов в день
0,1
всего 25
Упоминаний
2
каналов
Охват размещения
оценка
1/24сутки в ленте
385
1/48двое суток
441
1/72трое суток
475

Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.

Посты

  • 14 авг.4352418

    Мой воркфлоу с ИИшками сейчас У меня счас несколько подписок: • антропик 20$ (для разработки) • опенай кодекс 20$ (для разработки) • и российская hub.neuraldeep.ru (в основном не для разработки) Пользую через claude code консольный, через него можно пользовать и модели сlaude нативно, и любую другую модель подцеплять. Для этого можно задать/отредактировать в энвах переменные ANTHROPIC_BASE_URL, ANTHROPIC_MODEL. Либо если хочется вариант поинтереснее, то есть инструмент ccs, который через поднятие локального прокси CLIProxy позволяет прокидывать запросы в формате claude code и конвертировать его в формат нужного провайдера (OpenAI/Gemini/Codex/Kimi…), а заодно и авторизовываться по OAuth. Какой профит все модели гонять через харнесс Claude Code? В едином месте собрана вся история моих взаимодействий с иишками, папка .claude становится как бы средой, накапливающей память обо всех проектах (менеджер сессий), процессах, что я делаю по работе и нет. Отсюда из этой среды можно черпать инфу для статей, идей, вспоминать какие-то моменты и возвращаться, то есть по сути это хранилище ВСЕГО контекста взаимодействия меня/ИИ. Кстати, сам CC именно как менеджер сессий не оч, и когда сессий становится много, ориентироваться начинает становиться сложно, для этого есть спец тула codbash, которая позволяет менеджерить все свои cc, codex и прочие ии-сессии на компутере и удобно к ним возвращаться (кстати, с недавних пор эта тулза стала уметь запускать сессии прямо внутри себя). Важный момент: сессии по умолчанию в СС подчищаются/ротируются раз в месяц, это регулируется настройкой ~/.claude/settings.json (можно выставить большое значение, чтобы старые сесии не пропадали + бэкапить с помощью codbash-а, там есть спец команда). Например, сейчас с начала года у меня накопилось 2363 сессий (по работе и не по работе). Все сессии запускаю в режиме --dangerously-skip-permissions, чтобы не просило лишний раз разрешений, а просто делало работу. Для защиты от случайных деструктивных действий использую защиту. В качестве редактора использую zed, иишные штуки там в основном не пользую, только для редактирования кода и просмотра диффов. Раньше для управления терминалами использовал отдельное приложение superset + iterm2, теперь перешёл на мультиплексор herdr + iterm2 (плюс в том, что это не приложение на electron и не ест много памяти). Есть ли разница между антропиком за 20$ и кодексом за 20$ в плане решения ежедневных задач? Я их использую обычно вместе, типа опус 4.8/5 делает задачу, гпт 5.5/sol/luna ревьюит или наоборот. Плюс запускать разные модели в одном харнессе: они имеют лёгкий доступ к сессиям друг друга (буквально можно указать id сессии и модель разберётся, как туда попасть). В харнессе codex недавно появилась возможность запуска сессий/общения меж сессиями не вручную, а самим агентом, в CC пока нет, ожидаю. Насчёт именно ревью кодексом опуса есть спец средство для этого — плагин codex для cc, которое позволяет запустить ревью кода кодексом прям внутри сессии клода /codex: review, запустится субпроцесс. Также есть /codex:codex-rescue для того, чтобы просто "спросить совета" у codex. Скорее всего эта инфа устареет уже через месяц и полностью превратится в тыкву через год, но всё же решил зафисировать текущее ссотояние дел, может кому пригодится. #Лаборатория_веб_платформы @web_platform | Поддержать блог 💙

  • Hermes vs OpenClaw В комметах к прошлому посту @fogrew спросил, чем Hermes отличается от OpenClaw 1. OpenClaw идеологически и архитектурно построен как гейтвей, а Hermes как самообучающаяся агентная среда. Соответственно Hermes польше подходит для создания персональных ассистентов, которые учатся и со временем подстраиваются под пользователя. Агент на Hermes из коробки явно дополняет свои скиллы и память во время его использования (и сообщает об этом), у OpenClaw это всё довольно неявно происходило и не автоматом. 2. Hermes легче устанавливать и настраивать (причём настройки из коробки на 99% ок), чем OpenClaw + у Hermes меньше требования к железу, на котором он развёрнут. На одной VPS, где был раньше развёрнут один Openclaw, у меня сейчас уже крутятся два Hermes и ещё есть много оставшихся ресурсов. 3. API у обоих примерно одинаковый, поэтому миграция OpenClaw -> Hermes проходит по факту в одну команду. Вкратце, у обоих есть гейтвей, пейринг с мессенджерами (поллинг/вебхук), крон, скиллы/тулы, память. 4. У Hermes есть полноценный десктоп-клиент для тех, кто хочет работать не через CLI/телеграм. То есть в двух словах: Hermes лучше для перс ассистентов, OpenClaw как общий гейтвей (но надо иметь в виду, что его ещё надо дополнительно настраивать + он требует больше ресурсов). #Лаборатория_веб_платформы @web_platform | Поддержать блог 💙

  • 8 июл.1 05558

    Недавний инцидент с ДЦ сподвиг меня причесать всё на VPS с ботом-дайджестёром. Раньше было как: просто предустановленный образ с OpenClaw, ну и я там прям в системе был запущенный лонг-поллинг телеграма (чтоб бот обрабатывал команды старта/подписки/отписки), серты, настроенный туннель на другой сервер, донастроенный nginx. Во всём этом богатстве жил клешнебот openclaw с нужными скиллами и по собственному крону запускал node-скрипты для сбора дайджестов, суммаризации и процесса апрува/ревью получившихся черновиков, а затем отсылки сообщений подписчикам бота. Потом я на тот же сервер накрутил ещё self-host хранилище Obsidian + сервер WebDAV для синхронизации его между моими устройствами. И в того же бота добавил скиллы по работе с заметками obsidian: типа найти инфу в хранилище, добавить что-то, удалить прям через тг-бота. В общем, мигрировать всё это хозяйство на другой VPS как-то казалось сложным, поэтому всё откладывал. И тут возникла ещё идея поднять персонального агента-ассистента для родственников, чтоб пользовались для бытовых целей иишками, не продавая данные корпорациям. В общем, поднял на том же серваке Coolify, начал рассовывать всё по контейнерам. Основной профит в том, что можно из ui управлять сервисами, прописывать энвы, запускать деплои. А самое главное, что в случае чего, проще мигрировать на другой сервер. Попутно переключился с ручного nginx на Traefik, встроенный в Coolify, маршруты описаны в конфигах, серты выпускаются на лету. WebDAV для хранилища Obsidian засунул в отдельный контейнер. При этом само хранилище осталось в общей системе, в том числе бэкапилка в github. Там когда прилетают по WebDAV правки с отдельного устройства, по крону раз в 15 минут чекаются изменения в гит-репе и автокомитятся в github (надо будет, кстати, крон-бэкапилку тоже вынести в отдельный контейнер, пока осталась в системе вынес). Затем openclaw-агента, который собирает дайджесты и помогает мне с obsidian-ом, мигрировал на Hermes (переосмысленный подход клешнеботоводов в самообучающуюся систему) и посадил в свой отдельный контейнер. И заодно подцепил другую модель, поумнее. Была qwen3.6-35b-a3b, а стала kimi-k2.6. С qwen периодически ботяра запутывался: то скиллы не прочтёт, то войдёт в цикл и несколько постов отправит. С kimi-ком счас чётко, методично работает и минималистично-молчаливо общается. И, собственно, поднял в соседнем контейнере ещё одного Hermes-агента, уже для семьи. Со своими конфигами, душой, а также мозгами (пробую модель gemma-4-31b, она такая же болтливая, как qwen3.6-35b-a3b, но вдобавок мультмодальная, что важно для бытового агента). Hermes-бота можно настроить как командного ассистента (а чем семья не команда?). Поставил заодно родственниками отдельный ui-клиент для работы с агентом (типа claude desktop и иже с ними) для тех, кто на компутере работает, но в терминал не умеет. Модели все юзаю с лампового российского хаба hub.neuraldeep (не сочтите за заказную рекламу, вот честная рефералка) в рамках подписки. Кстати, с проблемного ДЦ в итоге так и не мигрировал 😂 Что ж, поиспытываю судьбу ещё раз. #Лаборатория_веб_платформы @web_platform | Поддержать блог 💙

  • 2 июл.1 29075

    вчера мой ботик @web_platform_pulse_bot не прислал новости, а всё потому что кукольный театр сгорел один дата-центр в Нидерландах перегрелся, а дальше всё как-то очень интересно начало происходить: сломалась система кондиционирования в ДЦ (стационарные чиллеры), заказали мобильный чиллер, он приехал, но сразу не получилось подключить, тк понадобились силовые кабели, заказали их, а там уже и ночь настала, поспим до утра, утром проснулись-потянулись, подключили кабели, давай подключать резервный чиллер, подключили, теперь надо дождаться, пока охладится помещение, проверить, что всё ок работает и всё поэтапно включить обратно бэкапа конфигов/энвов у меня конечно же не было, поэтому пока сервер не работал, выгрузить их я не мог, чтоб в другом месте развернуть походу теперь надо переезжать в общем, как-то с софтом всё попроще будет, чем с железом 😅 хотяяя

  • 22 июн.1 47454

    4 мая -> 20 июня, столько провисел мой pr в zed до мерджа зато теперь тема superset доступна через сам zed https://zed.dev/extensions/superset-theme 👍

  • 22 июн.1 23372

    Как superset.sh привёл меня к собственной теме для Zed В последнее время моя ежедневная работа всё больше смещается в терминал. Когда параллельно открыто несколько проектов и у каждого по несколько вкладок в терминале, обычный плоский список табов терминала…

  • 18 июн.1 498169

    Как пошарить системное видео/аудио в расширение браузера Недавно увидел в одном расширении в Chrome интересное решение, расковырял исходники, решил поделиться. Функциональность расширения — запись звука, сохранение в файл и дальнейшая отправка его в сервис транскрибации. Так вот интересный момент как именно расширение получает аудио. Допустим вы открываете во браузере Google Meet, десктопный Zoom или любой другой апп для созвонов. Начинаете созвон, приложение/браузер стримит туда-сюда звук и видео. И этот поток направляется в браузерное расширение. В Chrome при этом надо дать явное разрешение и затем появляется уведомление, что происходит шаринг вкладки или всей системы в расширение (аналогичным образом вы обычно шарите свой экран в веб-приложение, а тут веб-приложением выступает браузерное расширение). Как это работает под капотом. Там Manifest V3 приложение. Микрофон получается через getUserMedia из (Media Capture and Streams API). А вот звук стрима берётся через getDisplayMedia — это уже Screen Capture API, в рамках которой браузер показывает системный диалог "чем поделиться". Таким образом и получается что угодно шарить в браузерное расширение. Потом два независимых потока, микрофон и собеседник, нужно свести в один. И делается это Web Audio API: const ctx = new AudioContext(); const mix = ctx.createMediaStreamDestination(); ctx.createMediaStreamSource(micStream).connect(micGain).connect(mix); ctx.createMediaStreamSource(tabStream).connect(tabGain).connect(mix); const combined = mix.stream; // снова обычный MediaStream, его и пишем То есть по сути Web Audio используется как микшер. В процессе там заодно можно что-то дополнительно обработать, например, усилить микрофон, а на выходе получить единый поток. Ок, поток получили, теперь задача его записать. Для этого используется MediaStream Recording API и интерфейс MediaRecorder. Пишется не одним куском в конце, а порциями: start(timeslice) отдаёт данные кусками по ходу записи, и если что-то пойдёт не так на втором часу разговора, то всё не будет потеряно. У WebM при этом есть давняя болячка — MediaRecorder не проставляет длительность в заголовок, и готовый файл выглядит «бесконечным» для плееров и сервера. Лечится это пост-обработкой блоба, дописыванием правильных метаданных уже после остановки. То есть кратенько: Media Capture and Streams и Screen Capture добывают MediaStream (с устройств или с экрана), Web Audio умеет этот поток обрабатывать и микшировать, а MediaStream Recording берёт готовый MediaStream на вход и сериализует его в сжатые байты — Blob в webm/mp4/ogg, которые уже можно сохранить на устройство или отправить в какой-то внешний сервис дальше. И ещё один интересный момент уже про само браузерное расширение. Вообще оно работает в service worker, у которого нет доступа к DOM и всем веб-API. И чтоб это обойти используется Chrome-специфичное chrome.offscreen, которое создаёт полноценную "невидимую" страницу, где и выполняется код. #Лаборатория_веб_платформы @web_platform | Поддержать блог 💙

  • 21 мая1 56214

    #Лаборатория_веб_платформы Look Ma, это я в 2025 пишу фича-флаги прямо в CSS! /* обычные стили */ /* ... */ @container style(--wow-such-a-feature: true) { /* стили за фича-флагом */ /* ... */ } @container style(--wow-such-an-another…

  • 30 апр.2 3611114

    Как superset.sh привёл меня к собственной теме для Zed В последнее время моя ежедневная работа всё больше смещается в терминал. Когда параллельно открыто несколько проектов и у каждого по несколько вкладок в терминале, обычный плоский список табов терминала (у меня iTerm) слишком скукоживается. Не хватает ещё одного измерения: горизонтально — вкладки внутри одного проекта, вертикально — сами проекты. И тут узнал про superset.sh, и он мне зашёл. Получается такой 2D-терминал: слева список проектов, внутри каждого свои табы. Параллельно с увеличением количества времени проводимого в терминале меняется и роль редактора кода. Если раньше IDE была главным рабочим местом, то в агентоцентричной разработке "редактор" больше нужен для просмотра diff, точечных правок и удобной навигации по файлам. У меня эту роль уже около года выполняет Zed: быстрый, легковесный и менее прожорливый по ресурсам, чем VS Code. Теперь про смену контекста между режимом "терминала" и "редактора". В superset-е мне очень понравилась тёмная тема по умолчанию (такая тёплая ламповая), а при переходе в Zed была другая тёмная тема, о которую спотыкается глаз, когда много раз за день прыгаешь между "менеджером терминалов" и "редактором для проверки изменений". В общем, я собрал тему для Zed на основе темы superset. В целом, нужно было экспортнуть тему из superset и сопоставить с токенами темы в Zed. Так как это всё таки немного разные контексты, пришлось подтюнить тему в течение пары недель использования, пока окончательно не привык. В СПб сейчас начинаются белые ночи, поэтому больше счас сижу в светлой теме днём (на основной работе) и в тёмной после заката (на пет-проектах). Тему для Zed я опубликовал здесь https://github.com/juwain/superset-zed-theme. Скрины в комментах. #Лаборатория_веб_платформы @web_platform | Поддержать блог 💙

  • 3 апр.2 1444312

    Не теряемся Раньше я составлял и публиковал дайжесты #Пульс_веб_платформы. Дело это было довольно муторное и меня хватило на выпуск где-то примерно 80 еженедельных дайджестов. В процессе я каждый четверг пропускал через себя несколько других дайджестов, около сотни тг-каналов и примерно столько же отдельных RSS-блогов. С момент последнего выпуска прошло около 10 месяцев, одно время я совсем бросил что-то читать, но потом интерес вернулся. Попробовал собрать несколько дайджестов, но мозг сразу сказал, что заниматься написанием дайджестов больше не будет. Но читать дайджесты при этом хочется! И я решил построить автоматизированный пайплайн сборки дайджестов (прежде всего для себя, но может быть и вам зайдёт). В общем, дождался блокировки телеги и вынес дайджест в отдельного бота @web_platform_pulse_bot. В нём ежедневно утром бот публикует примерно 10 ссылок с самым интересным, что произошло в индустрии за прошлые сутки. Аннотации пишу уже не я, а модель, поэтому в душевности дайджест, конечно, потерял. Но в информативности, пожалуй, даже прибавил, так как посты стали ежедневными вместо еженедельных, и покрывают большее число материалов. Если хочется за пару минут понять, что там произошло в целом, достаточно краткой сводки утром по диагонали вместо чтения объёмных рассылок. Я умышленно отделил авторский контент блога от генерёжки дайджеста, поэтому он будет именно в отдельном боте @web_platform_pulse_bot. Помимо бота дайджест публикуется на сайт https://juwain.github.io/web-platform/pulse/ и в RSS https://juwain.github.io/web-platform/pulse/rss.xml. Основной веблог тоже перевёз на gh pages https://juwain.github.io/web-platform/blog/ и в RSS https://juwain.github.io/web-platform/rss.xml (на очередную оплату домена webplatform.tech блог, увы, не заработал). Отдельно настроил публикацию в зеркало на статику яндексовского sourcecraft. Там ресурсы доступны даже на парковке, так как Яндекс в белых списках. Вот зеркало дайджеста https://juwain.sourcecraft.site/web-platform/pulse/ и его RSS https://juwain.sourcecraft.site/web-platform/pulse/rss.xml. А также зеркало основного блога https://juwain.sourcecraft.site/web-platform/blog/ и его RSS https://juwain.sourcecraft.site/web-platform/rss.xml. Если интересны технические детали реализации, поставьте реакций, я тогда позже напишу отдельный пост, как эта фиговина работает в более-менее автономном режиме и в лучшем случае требует от меня поревьюить подготовленные тексты через интерфейс TG. В комментах приложу пару примеров дайджестов за прошлые дни. #Лаборатория_веб_платформы @web_platform | Поддержать платформу 🌟

  • 22 мар.1 9733255

    Скриншот-тестирование компонентов в Docker В нескольких проектах, где я работал, пробовали внедрить скриншот-тестирование компонентов. Принцип работы такой: 1) меняем компонент 2) делаем эталонный скриншот, сохраняем в репе 3) повторяем на всех компонентах 4) при повторных изменениях запускаем тесты, в которых сравниваются эталонные скриншоты и текущее отображение компонентов 5) если все расхождения запланированные, меняем эталонные скрины; если есть незапланированные расхождения, поздравляю, тесты нашли регресс! Такие тесты хорошо подходят для теста вёрстки элементов ui-kit-а (многочисленные состояниях ховера, фокуса, разные режимы компонента) или же каких-то критичных компонентов (форма логина, чекаут), которые никак нельзя случайно поломать. Снепшотные тесты, юниты, e2e тут не помогут, нужно именно сравнение скринов. Звучит хорошо, но есть одно НО. Во всех случаях на моей практике дело упиралось в то, что скриншоты снимаются разными разработчиками на разных машинах с разными ОС. И в зависимости от этого скриншоты начинают расходиться. Шрифты другие. Субпиксельный рендеринг другой. Антиалиасинг другой. Также отличаются элементы форм. И тест падает, хотя визуально всё ок. Вместо помощи тесты начинают мешать и бесить. Логично было бы предположить делать скриншоты на одной машине, например, вынести этот процесс на CI/CD или на отдельный сервер, но обычно с этим в компаниях сложно, нужно всё согласовывать, заводить, что есть заморочь. И тут изучая Docker открыл для себя идеально подходящую под кейс фичу! Через Docker можно связать файловую систему хоста (ваша машина) с файловой системой запущенного контейнера. То есть храним скрины по прежнему в репо (развёрнутом у каждого разработчика), монтируем папку с ними внутрь Docker-контейнера, снимаем скриншоты, сравниваем, при необходимости обновляем. Внутри контейнера один и тот же образ с фиксированной ОС, фиксированной версией браузера, фиксированными шрифтами. И соотвественно таким же макаром запускается в CI. Собрал пруф оф концепт. Что там вкратце, происходит: Storybook изолирует компоненты, Playwright делает скриншоты, Docker обеспечивает одинаковый рендеринг. Оркестрация через docker-compose.yml (именно там указывается, какие локальные папки монтируются в контейнер): services: visual-tests: build: . volumes: # Persist screenshots - accessible from host - ./__screenshots__:/app/__screenshots__ # HTML report for visual diff - ./html-report:/app/html-report # Test results (traces, screenshots on failure) - ./test-results:/app/test-results # Source files for quick iteration (read-only) - ./src:/app/src:ro environment: - CI=true command: sh -c "npm run storybook -- --host 0.0.0.0 & sleep 15 && npx playwright test --project=visual" Docker-образ с Playwright официальный от Microsoft уже содержит браузеры и все зависимости. FROM mcr.microsoft.com/playwright:v1.48.0-noble Каждый визуальный тест — это три действия: открыть стори, дождаться рендера, сравнить скриншот. Storybook рендерит в статическом режиме каждый отдельный компонент по адресу /iframe.html?id=${storyId}&viewMode=story, ждём пока загрузятся картинки и шрифты, можно снимать скриншот Playwright-ом и сравнивать тоже им. Пример теста кнопки: test.describe('Button', () => { test('hover', async ({ page }) => { const component = await gotoStory(page, 'design-system-button--primary'); const button = component.locator('button.button').first(); await button.hover(); await expect(component).toHaveScreenshot(); }); }); Особенности настройки Playwright: можно оставить небольшой задел на случайные расхождения, выключить анимации, спрятать каретку в инпутах. toHaveScreenshot: { maxDiffPixels: 100, animations: "disabled", caret: "hide", }, После прогона тестов формируется HTML-репорт: интерактивный diff, где можно посмотреть, что именно изменилось (приложил скрин, как это выглядит в комментах). #Лаборатория_веб_платформы @web_platform | Поддержать платформу ⭐️

  • 1 мар.1 6234121

    End-to-end разработчик Деление на фронтенд и бэкенд никогда не было про технику. Это было больше про бизнес-процессы и найм: в индустрии удобнее искать заменяемых специалистов на узкий скоуп. Фронтендер имплементит "клиентскую" логику, бэкендер — API и "серверную" логику. Но по сути это единое целое и деление, если посмотреть свежим взглядом, весьма условное. Я прекрасно помню времена, когда фреймворки не затачивались конкретно на фронт/бэк, а были про веб-разработку проекта целиком. И сейчас это деление начинает терять смысл. ИИшки привносят собой инфляцию ценности навыков (и стоимости строк кода). Уметь писать код стоит меньше, чем год назад. И будет стоить ещё меньше через год. Причём стоит меньше и в деньгах, и в самой ценности навыка: знания становятся все более и более общедоступны и легкодоступны, и само понятие конкретного навыка — это теперь не что-то труднодостигаемое и "выстрадываемое" потом и кровью. Приходит эпоха полнофункционального разработчика (олды тут? привет, вебмастера). Это как бы «фуллстек» в старом понимании (например, в связке React + Node) + одновременно, который понимает систему целиком от и до, может и обозревать верхнеуровнево, и "зумиться" до детальной имплементации, настраивает инфраструктуру, валидирует, что и как система делает, а главное — следит, как система соотносится с бизнесом, насколько качественно решает его проблемы. End-to-end-разработчик. Карьерный путь становится короче и интенсивнее. "Junior" в привычном смысле исчезает — вместо него "junior senior": человек приходит уже с наработанным опытом через пет-проекты, симуляционные окружения. С образованием вообще всё просто небывало круто. Как никогда раньше обучение может быть безостановочным процессом и не привязанным к конкретному обучающему вендору — селф-обучение выходит на первый план, а бизнесы напрямую предоставляют свою инфру для специализации в нужном контексте. Реагировать на происходящее можно по-разному. Отрицать, игнорировать, плыть по течению или против. Но если хочется сохранить привычные заработки и скорость их роста, в обозримом будущем все пути ведут к тому, чтобы брать на себя бо́льшую ответственность. Для разработчика это или уходить в пипл-менеджмент, или же расширять и углублять технику. Я за свою карьеру два раза проходит цикл "разраб -> тимлид -> разраб" и понял, что не хочу копать в менеджмент дальше. Поэтому сейчас отзываясь на вызовы нового времени выбираю второе. Так что буду уделять больше своего времени частям веб-разработки и платформы, которые выходят за пределы интерфейса в браузере: инфраструктуре, "серверу", инструментам сборки и доставки, проектированию систем. И вникать в зарождающуюся роль e2e-разработчика — теперь больше "пчеловода", чем "собирателя". Думаю, это также отразится и на содержании блога. Всем послушных пчёл! 👁️ #Фикшн_веб_платформы @web_platform | Поддержать платформу

  • 18 февр.1 7952113

    npm lifecycle scripts TIL, что в npm есть lifecycle scripts. Перед и после стандартных команд типа dev, build, test есть "хуки", на которые можно подцепить нужные дополнительные команды. npm run dev | predev → dev → postdev npm run build | prebuild → build → postbuild npm test | pretest → test → posttest Добавляете в package.json скрипт с префиксом pre или post — npm запустит их с соответствующем порядке: { "scripts": { "build:client": "node esbuild.client.mjs", "predev": "npm run build:client" "dev": "tsx src/server/index.ts", } } Сначала predev соберёт клиент, dev запустит сервер. Полезно, когда перед запуском надо что-то подготовить — собрать ассеты, проверить типы, создать папки. Что можно с этим сделать: - prepublishOnly — проверки перед публикацией пакета в npm - prebuild — генерация кода или очистка папки dist - postinstall — автоматические действия после npm install Дока #Лаборатория_веб_платформы @web_platform | Поддержать платформу 💕

  • 13 февр.1 5942610

    Что нового Baseline Widely Available, часть 4 ...продолжение Web APIs Offscreen Canvas — рендеринг canvas в отдельном потоке без зависимостей от DOM. const offscreen = canvas.transferControlToOffscreen(); worker.postMessage({ canvas: offscreen }, [offscreen]); Мнение: 4 из 5, по идее довольно мощная возможность для оптимизации, опять же в связке с web worker-ом, куда можно кинуть "внеэкранную канву" для рендера чего-либо тяжёлого. — Screen Orientation — API для управления ориентацией экрана. await screen.orientation.lock('landscape'); Мнение: 4 из 5, мастхэв для работы с мобилками, пригождалось. — Server Timing — API для получения информации о таймингах запросов с сервера. const entries = performance.getEntriesByType('navigation'); const serverTiming = entries[0].serverTiming; Мнение: 4 из 5, это мощное дополнение к Web Performance API, правда требует настройки и бэка/сервера, чтобы отправлялись нужные заголовки. — Push Messages — API для push-уведомлений. const subscription = await pushManager.subscribe(); Мнение: 5 из 5, о, думаю, появлению этого API на iOS для PWA очень порадовались банки и другие выпиленные из сторов компании; всему, что убирает монополию вендоров в пользу веб-платформы ставим пятюню. — MathML — разметка математических формул без картинок и JS-библиотек. <p> The fraction <math> <mfrac> <mn>1</mn> <mn>3</mn> </mfrac> </math> is not a decimal number. </p> Мнение: 4 из 5, вот это очень хоть и узкоспециализировано, но на мой взгляд тоже круто, так как позволяет latex-у и подобным инструментам, избавиться от доп кода для рендера формул. #Пульс_веб_платформы @web_platform | Поддержать платформу ⭐️

  • 11 февр.1 304208

    Что нового Baseline Widely Available, часть 3 ...продолжение JavaScript Array findLast() и findLastIndex() — поиск в массиве в обратном порядке. const array = [5, 12, 8, 130, 44]; const isLargeNumber = (element) => element > 100; console.log(array.findLast(isLargeNumber)); // 130 console.log(array.findLastIndex(isLargeNumber)); // 3 Мнение: 3 из 5, хорошо, когда удаётся утилиты заменять на встроенные методы, так что мелочь, а приятно. — Array by Copy — методы toSorted(), toReversed(), toSpliced(), возвращающие новый массив без изменения оригинала. const arr = [1, 2, 3]; const sorted = arr.toSorted(); const reversed = arr.toReversed(); Мнение: 3 из 5, это вот из разряда "теперь надо запомнить, что так делать можно", а то по привычке спредишь массив перед любой мутацией — Import Maps — декларативное управление импортами через JSON. <script type="importmap"> { "imports": { "lodash": "/node_modules/lodash-es/lodash.js", "utils": "/src/utils.js" } } </script> Мнение: 4 из 5, вот это, кстати, довольно важная непроходная фича, по сути позволяющая на ES-модулях построить проект без особой сборки, чтобы само собиралось в рантайме (но пригодно, на мой взгляд, в небольших проектах). — JavaScript Modules in Workers — использование ES-модулей в Web Workers с { type: "module" }. // worker.js import { processData } from './utils.js'; self.onmessage = (e) => { const result = processData(e.data); self.postMessage(result); }; Мнение: 2 из 5, с одной стороны, да, появилась возможность импортировать ES-модули, с другой — в этом режиме они импортируются под CORS-ом, а в классических воркерах доступен и `no-cors`-режим; в общем годная тема, ещё больше можно вынести в воркер. — requestAnimationFrame() in Workers — анимации в Web Workers. // worker.js function animate() { // логика анимации requestAnimationFrame(animate); } animate(); Мнение: 2 из 5, тоже плюсом к предыдущему пункту, если работаете с воркерами, то можно более плавно встраивать результат вычисления обратно в основной поток. — Compression Streams — API для сжатия/распаковки данных в формате gzip или deflate. const compressed = readableStream .pipeThrough(new CompressionStream('gzip')); Мнение: 3 из 5, может быть полезно для сжатия пользовательских файлов или распаковки полученных сжатых файлов, приятно, что заехало прям в платформу, можно не использовать доп либы. — Constructed Stylesheets — программное создание стилей через CSSStyleSheet и их совместное использование через adoptedStyleSheets. const sheet = new CSSStyleSheet(); sheet.replaceSync('.my-class { color: blue; }'); document.adoptedStyleSheets = [sheet]; Мнение: 2 из 5, более навороченный способ добавлять динамически новые стили, хз, может будет полезно авторам runtime-стилизационных библиотек. продолжение следует... #Пульс_веб_платформы @web_platform | Поддержать платформу ⭐️

  • 9 февр.1 6011633

    playwright-cli Тут вышел https://github.com/microsoft/playwright-cli, более эргономичный, чем MCP, способ запускать ботом безголового playwright для выполнения действий в браузере. Да, собственно, не обязательно ботом, можно просто в рамках CLI-API написать скрипт для автоматизации действия в браузере: playwright-cli open https://demo.playwright.dev/todomvc/ --headed playwright-cli type "Buy groceries" playwright-cli press Enter playwright-cli type "Water flowers" playwright-cli press Enter playwright-cli check e21 playwright-cli check e35 playwright-cli screenshot Вот эти вот e21 и e35 — это наименования DOM-нод в открытом сайте. Командой open сайт открывается и записывается его снепшот в виде yaml-файла. Каждая нода помечается своим айдишником. По необходимости можно вызывать playwright "с головой": playwright-cli open https://playwright.dev --headed Для ботов прописаны доки для выполнения рутинных задач: - Request mocking — перехват и мок запросов - Running Playwright code — выполнение playwright-скриптов - Browser session management — управление браузерными сессиями - Storage state (cookies, localStorage) — запись и чтение из браузерного хранилища - Test generation — генерация тестов после взаимодействия с сайтом - Tracing — запись трейсов - Video recording — запись видео

  • 5 февр.1 195217

    Что нового Baseline Widely Available, часть 2 ...продолжение CSS Two-value display property — свойство display теперь принимает два значения для явного указания внешнего и внутреннего режима layouts. Например, inline flex или block flow. .card { display: inline flex; } .container { display: block flow; } Мнение: 2 из 5, любопытно, но не более. — overflow: clip — обрезка содержимого без создания скроллов, с возможностью обрезки только по одной стороне .nav-bar { overflow-x: clip; overflow-y: visible; } Мнение: 4 из 5, полезно, если нужно включить скролл по одной стороне + также это значение overflow, в котором не создаётся новый formatting context. — overscroll-behavior — управление поведением при прокрутке за границы. .container { overscroll-behavior: contain; } Мнение: 3 из 5, очень узкоспециализированная фича, но может быть крайне полезна для управлением мульти-скроллом. — outline — свойства для стилизации линии вокруг элемента вне border, не влияющие на layout. .element { outline: 2px dashed red; outline-offset: 5px; } Мнение: 3 из 5, фича-то старая, но был баг в Safari, который починили в 03.2023. — :nth-child() of <selector> — более точный выбор элементов с фильтром по селектору. li:nth-child(odd of .active) { background: yellow; } Мнение: 4 из 5, прикольная штука для условной стилизации, полезно вспомнить перед решением реализовать такое на JS. — Media Query Range Syntax — новый синтаксис для медиавыражений с диапазонами. @media (400px <= width <= 800px) { /* стили */ } Мнение: 4 из 5, синтаксический сахар, нравится, что наконец не нужно каждый раз вспоминать и перебирать варианты min/max-width. — Resolution Media Query — медиавыражение для применения стилей на основе плотности пикселей устройства. @media (min-resolution: 2dppx) { /* стили для high-DPI экранов */ } Мнение: 2 из 5, узкоспециализированная фича, но может пригодиться для детальной стилизации для разных мобильных устройств. — Trigonometric Functions — sin(), cos(), tan() в CSS для математических вычислений. .element { transform: rotate(calc(sin(45deg) * 1turn)); } Мнение: 2 из 5, любопытно, но слишком хардкорно, малоприменимо в реальной жизни. — calc() Keywords — математические константы e, pi, infinity, NaN в CSS math функциях. .element { font-size: calc(var(--base-size) * pi); height: calc(100vh * sin(pi / 2)); } Мнение: 1 из 5, не могу придумать, где это применить. — font-palette — выбор цветовой палитры из шрифта, с возможностью переопределения отдельных цветов через @font-palette-values. .element { font-palette: alternate; } Мнение: 1 из 5, малополезная фича, применимая только для "цветных" шрифтов, не стоит внимания — Style Containment и Inline-size Containment — изоляция стилей элемента. style ограничивает расчёт счётчиков и кавычек внутри элемента, а inline-size предотвращает установку inline-размеров элемента его содержимым, ускоряя рендеринг. .widget { contain: style; } .container { contain: inline-size; } Мнение: 3 из 5, мелкие малополезные фичи, style может пригодиться разве что в нестандартных нумерованных списках; inline-size, могу только в теории представить, что может быть полезно в разного рода wysiwyg-ах (за исключением контейнерных запросов, которые без этой шутки не заработают). — HTML / DOM inert — атрибут для отключения элементов от взаимодействия и accessibility tree. Элементы не получают фокус и не реагируют на клики. <div inert> <button>Неактивная кнопка</button> </div> Мнение: 4 из 5, мощная и простая фича, хороший юзкейс для ограничения пределов фокуса при показе модальных окон: модалка работает, body под ней за inert-ом. продолжение следует... #Пульс_веб_платформы @web_platform | Поддержать платформу ⭐️

  • 4 февр.1 9303631

    Что нового Baseline Widely Available, часть 1 В прошлом году (+ в январе 2026) довольно много платформенных фич достигли статуса Baseline Widely Available — это значит, что они поддерживаются во всех основных браузерах уже 30 месяцев! А это повод бескомпромиссно тащить их в прод проверить аналитику по пользовательским устройствам и браузерам в вашем проекте (скорее всего ваши пользователи уже обзавелись браузером, которые эти фичи поддерживают). Собрал списком все фичи с кратким описанием и моими комментами к их использованию. CSS Container Queries — применение стилей на основе размеров родительского контейнера, а не viewport. Позволяет создавать адаптивные компоненты, которые реагируют на свой контейнер. .card { container-type: inline-size; } @container (min-width: 300px) { .card { background-color: lightblue; } } Мнение: 5 из 5, но требует перестроить майндсет в целом при работе с UI (то есть не только вам как разработчику, но ещё из продукту и дизайнеру, часто думающим "мобилками"). Хорошо ложится на UI-киты и разработку изолированных компонентов. — Individual Transform Properties — отдельные свойства translate, scale, rotate вместо одного transform. Упрощает анимации и улучшает читаемость кода. .element { translate: 20px 10px; scale: 0.8; rotate: 90deg; } Мнение: 3 из 5, приятный сахар, помогает сократить повторящийся код при написании трансформов, легко внедрить. — Motion Path — анимация элементов вдоль заданного пути с помощью offset-path. .element { offset-path: path('M10 10 L 100 100'); animation: move 2s linear infinite; } Мнение: 2 из 5, специфичная, но прикольная фича, но если появится подходящая задача и вовремя вспомнить, можно избежать использования JS для анимации движения элемента по траектории. — Grid Animation — анимация свойств grid-template-columns и grid-template-rows. .grid { display: grid; grid-template-columns: 1fr 1fr; transition: grid-template-columns 0.3s; } .grid:hover { grid-template-columns: 1fr 2fr; } Мнение: 2 из 5, в целом прикольная фича для разъезжающихся динамических лейаутов, но применимость нечастая. — animation-composition — выбор способа комбинирования анимаций, влияющих на одно свойство. .element { animation-composition: add; /* replace, add, accumulate */ } Мнение: 2 из 5, если делаете руками CSS-анимации, может пригодиться, иначе не будет полезно. — color-mix() — смешивание двух цветов в заданном цветовом пространстве. Полезно для создания светлых/тёмных оттенков. .element { background: color-mix(in srgb, red 50%, white 50%); } Мнение: 4 из 5, чрезвычайно мощная штука, если настраиваете собственную дизайн-систему, стайлгайд или UI-кит в проекте. — color() — выбор цвета из указанного цветового пространства. Поддерживает wide-gamut пространства вроде display-p3 для более насыщенных цветов. .element { color: color(display-p3 0.5 0.2 0.8); } Мнение: 4 из 5, аналогично мнению про color-mix(). — Lab и LCH — цветовые пространства с перцептивной равномерностью. Lab использует прямоугольные координаты, LCH — полярные. Oklab и OkLCh — цветовые пространства, разработанные для лучшего соответствия человеческому восприятию цвета. OkLCh — полярный вариант Oklab. .element { color: lab(50% 20 -30); background: lch(60% 50 150); color: oklab(0.5 0.2 -0.1); background: oklch(0.6 0.5 120); } Мнение: 4 из 5, формат oklch может также пригодиться для гибкой настройки цветовой палитры и её производных в проекте. — Small, Large, Dynamic Viewport Units — единицы dvh, svh, lvh для учёта UI мобильных браузеров. sv* — минимальный размер, lv* — максимальный, dv* — динамический. .element { height: 100svh; /* 100% минимального viewport height */ width: 100dvw; /* 100% динамического viewport width */ } Мнение: 4 из 5, если вы когда-нибудь боролись с fullscreen-высотой в вёрстке на мобилках, то в следующий раз присмотритесь к этим значениям. продолжение следует... #Пульс_веб_платформы @web_platform | Поддержать платформу ⭐️

  • 16 янв.2 2313489

    react-best-practices Тут Vercel подогнали мозгов для ваших frontend-агентов набор бестпрактисов и антипаттернов по React, можно установить в виде скиллов в ваш любимый агент или просто почитать. Темы, рассматриваемые внутри: устранение вотерфоллов, оптимизация размера бандла, SSR, дата-фетчинг на клиенте (жаль, что без tanstack, а только swr), оптимизация ререндеров, перфоманс рендеринга и JS, а также ещё немного мелочей. #Пульс_веб_платформы @web_platform | Поддержать платформу 🌀

  • 14 янв.1 6622714

    А вы заметили, что со всеми этими ии-движухами как-то морально проще стало экспериментировать с новым софтом и подходами в работе. Раньше ну узнаешь, что какая-то там либа вышла, ну подумаешь, что надо когда-нибудь попробовать, и всё на том. Ну максимум на свежем проекте или новом компе что-то свежее ставишь, пробуешь. А теперь как-то реально попроще со всем этим стало: узнаёшь, сразу пробуешь, профит (наверное это можно назвать таблеткой от FOMO, правда хоть это и купирует приступы, но провоцирует повторные 😁). Возможно на такой волне стоит присмотреться и к остальной экосистеме. Например, вот в pnpm подвели итоги прошлого года. В v10 много всего интересного. Самое важное — pnpm перестал доверять всем пакетам. Раньше pnpm install давал любому пакету в дереве зависимостей запускать произвольный код (preinstall, postinstall). Это само собой создавало вектор атак через supply chain. В v10 lifecycle scripts блокируются по умолчанию. Никакого preinstall/postinstall без явного разрешения. allowBuilds: esbuild: true nx@21.6.4: true Ещё одна фишка pnpm — content-addressable store (дедупликация файлов). В v10.12 сделали ещё шаг дальше — глобальное виртуальное хранилище. pnpm-workspace.yaml enableGlobalVirtualStore: true Раньше каждый проект имел свой node_modules. Теперь общие зависимости линкуются один раз глобально. А это: 1. Экономия диска — одинаковые графы зависимостей шарятся между проектами. 2. Быстрые установки — если 10 проектов используют react@19, pnpm линкует его один раз из глобального хранилища на машине. Для монорепозиториев и сложных настроек есть конфиги зависимостей. Это позволяет шарить конфиги pnpm (хуки, патчи, разрешения на билды) между проектами. Конфиги зависимостей устанавливаются в node_modules/.pnpm-config до основного графа зависимостей. # pnpm-workspace.yaml configDependencies: pnpm-plugin-my-company: "1.0.0+sha512-..." Это помогает шарить .pnpmfile.cjs хуки между репозиториями, централизовать патчи для patchedDependencies, поддерживать список пакетов, которым разрешено запускать build скрипты. Кроме того, pnpm давно умеет переключать версию Node.js для рантайма (не нужен nvm). В 2025 добавили Deno и Bun. // package.json { "devEngines": { "runtime": { "name": "node", "version": "24.6.0" } } } Pnpm сам скачает и будет использовать указанную версию для скриптов. Поддержка JSR — тоже прикольно, но пока что не особо актуально, как я вижу. Кроме того, ещё от себя добавлю, что в pnpm есть catalogs-алиасы (чтобы один раз в конфиге объявить набор зависимостей), workspaces (для организации монореп), возможность патчить зависимости (pnpm patch) и проверять их на актуальность (pnpm outdated) #Пульс_веб_платформы @web_platform | Поддержать платформу 🌀

Виталий и Платформа — tgindex