Команда проекта Pencil.dev обновила сервис и теперь он генерит любые интерфейсы по клику. В решение внедрили режим «Рой», который создаёт сразу несколько вариаций вашего проекта с помощью шести ИИ‑агентов параллельно. Можно грузить любые файлы и даже кастомные шрифты. Проект поддерживает Antigravity, Copilot, Gemini CLI, Opus 4.6, Sonnet 4.6 и даже OpenCode. Результат можно экспортировать во всех самых популярных форматах: PDF, JPG, PNG и WebP. Также стало доступно полноценное приложение для Windows.

Веб-разработка *
Делаем веб лучше
Особенность Joomla: json-значения для пользовательских полей и их рендер в subform и вне дочерней формы.
Опять длинное название, но куда уж без этого...
Итак, если вы делаете плагин пользовательского поля - его можно использовать через FieldsHelper. И в процессе ваши данные проходят через различные этапы обработки (недавно была статья на эту тему). И может так оказаться, что ваше поле хранит в rawvalue json (и в базе данных соответственно тоже), а в value вы на его основе рендерите значение. Это стандартный подход Joomla. Так работают, например, поля accessiblemedia. Однако, если вы поместили ваше поле в дочернюю форму (пользовательское поле типа subform и включили "Рендеринг значений = Да", то у вашего замечательного поля может появиться поломанный Json в value вместо нормального значения.
Например:
{"basePath":"...","layout":"..."}❓ Что там под капотом Joomla происходит?
В обычном потоке Joomla сначала вызывает событие
onCustomFieldsBeforePrepareField, а потомonCustomFieldsPrepareField.Внутри
subformже для подполей приrender_values=1вызывается только событие -onCustomFieldsPrepareField.Если преобразование значения (например,
json_decode) сделано в вашем плагине только вbeforePrepareField, оно не обработает данные для подполя и...В шаблоне поля строка заэкранируется (
htmlentities), кавычки превратятсяв тыквув"и вы получите кривой json, вместо вашего значения.
👉 Собственно полезный совет по Joomla:
Для полей, которые могут жить внутри subform, делайте нормализацию значения и в onCustomFieldsPrepareField тоже, не только в beforePrepareField.
Фронтенд 2026: взлеты и падения

Открываешь проект 2020 года и видишь знакомые имена в package.json: create-react-app, enzyme, moment.js, axios. Пять лет назад это был золотой стандарт. Сегодня же эти технологии вызывают у коллег искреннее недоумение: «Зачем это тут?»
Подготовили для вас быстрый, но очень полезный срез того, как за 5 лет поменялась ментальная модель фронтендера. Внутри инструменты реально умерли, разберемся почему SSR/SSG снова в игре, а TypeScript теперь почти must-have, узнаем почему фронтенд всё чаще = full-stack и что с этим делать.
Главный урок 2015→2025: фронтенд развивается циклически. Каждый цикл — это не «прогресс», а перебалансировка компромиссов. Читайте на Хабр в статье «Фронтенд 2026: что умерло, что выжило и что взлетело неожиданно»
Как понять, что ваш интернет-магазин вот-вот сломается: триггеры и решения для сайтов на Magento
Привет! Это Дмитрий Абакумов magento-разработчик в Далее, и Максим Бровко, тимлид в Далее.
Мы собрали 5 типичных симптомов, которые сигнализируют, что система уже нестабильна — на примере Magento, популярной CMS в сфере e-com.
В первую очередь скажем, что на Magento работают крупные бренды по всему миру. Она гибкая, масштабируемая, с богатой экосистемой. Однако без регулярных обновлений, контроля и DevOps-поддержки любой проект начинает замедляться, сбоить, а со временем — ломаться. Сигналы появляются заранее: сначала падает скорость, потом checkout, потом весь сайт.
Сигнал 1: падение скорости при большом трафике — во время акций и распродаж
Что проверить
Узкие места в БД: тяжелые SELECT, отсутствие индексов.
Дублирующиеся или вложенные вызовы блоков в Magento layout.
Как ведет себя cron и очередь задач.
Используется ли Varnish для FPC и/или Redis для общего кеша.
Как чинить
Настроить загрузку тяжелых блоков после рендера страницы — через AJAX.
Внедрить нагрузочное тестирование — k6, Siege, JMeter.
Перенастроить кеш Magento, включить компиляцию DI.
Заложить горизонтальное масштабирование или CDN.
Сигнал 2: долгая загрузка интернет-магазина при обычной посещаемости (более 3 секунд)
Что проверить
Логи Magento и серверов: timeouts, ошибки, блокировки.
Скорость отклика API.
Время сборки layout и количество подключаемых блоков.
Как чинить
Проанализировать профилировку — Xdebug, New Relic.
Отключить неиспользуемые плагины и модули.
Настроить мониторинг производительности и ошибок — New Relic, Grafana, Prometheus.
Сигнал 3: Клиенты доходят до оформления, но не покупают — особенно на мобильных устройствах
Что проверить
Как работает checkout: отрисовка, JS, блоки, сторонние виджеты доставки/оплаты.
Как отрабатывает кнопка «Оформить заказ» — все ли проходит быстро.
Нет ли тяжелых или повторяющихся вызовов.
Как чинить
Кешировать доступные блоки внутри checkout.
Упростить форму и ускорить ввод данных — DaData.
Включить асинхронную обработку заказов, если оформление занимает много времени.
Протестировать на реальных устройствах и подключить фронтовый логгер — Sentry.
Сигнал 4: когда починили один баг — появился другой
Что проверить
Архитектуру модулей: tight coupling, перезапись классов, обилие around-плагинов.
Есть ли автотесты, CI.
Как внедряются хотфиксы.
Как чинить
Минимизировать around-плагины и preference (перезаписей классов), отдавать предпочтение before/after-плагинам и observer.
Покрывать фиксы хотя бы базовыми unit/integration-тестами.
Настроить dev → stage → prod, релизный процесс с changelog.
Ввести code style, практику ревью и договоренности внутри команды.
Сигнал 5: CMS или модули устарели, все «на костылях» и никто не решается трогать
Что проверить
Версии ядра Magento и зависимостей.
Нет ли deprecated-библиотек, особенно JS.
Насколько кастомно переопределены шаблоны и классы.
Есть ли onboarding-документация, описание архитектуры, миграций, cron.
Как чинить
Если кастомный код внесен прямо в ядро Magento, то его нужно вынести в отдельные модули.
Сравнить архитектуру с best practices Magento и рекомендациями вендоров.
Написать README и настроить автоматизацию — Docker, Ansible.
Запланировать регулярные апдейты проекта.
Если у вас совпадают 3+ пункта — пора на техаудит
Magento почти всегда подает сигналы заранее: снижается скорость, растет количество багов, страдает checkout. Если таких симптомов становится много — пора остановиться и разобраться, что происходит внутри.
Что делать
Использовать метрики: PageSpeed, TTFB, логи ошибок.
Провести аудит: кеш, модули, layout, архитектура, DevOps.
Найти узкие места и критичные зависимости.
Выделить приоритеты по улучшениям и составить roadmap по рефакторингу.
Разбираемся как принимать звонки в браузере. Основы WebRTC\SIP\RTP.
Во многих коммуникационных продуктах возникает потребность работы с голосом. В этой серии постов разберемся как организовать прием звонков непосредственно из вашего web приложения. Какие есть варианты передачи звукового потока и какая может быть архитектура backend приложения, обеспечивающего его работу.
Начнем с самой простой в реализации схемы, в которой передача голоса осуществляется напрямую между браузером пользователя, открывшего ваше web приложение и серверами провайдера "виртуальной телефонии"(aka "виртуальная атс" ).
При этом вся мета информация о поступившем входящем звонке и событиях всего жизненного цикла звонка принимает ваш backend. У разных провайдеров телефонии набор событий и строения api может отличаться, но общая схема работы схожа.
Разберем основную схему организации передачи голоса. Браузер по сути работает как SIP‑телефон: сигнализация через WebSocket, медиа — по RTP.

1. Регистрация в сети
Оператор открывает страницу в браузере.
Браузер отправляет SIP REGISTER на SIP‑сервер (WebSocket/TLS).
SIP‑сервер отвечает 200 OK.
В интерфейсе показывается «Вы в сети» — оператор готов к звонкам.
2. Звонок
SIP‑сервер отправляет SIP INVITE в браузер.
Браузер показывает уведомление «Входящий».
Оператор нажимает «Принять».
Браузер запрашивает доступ к микрофону (getUserMedia) — внутреннее действие.
Браузер отправляет SIP 200 OK + SDP на SIP‑сервер.
SIP‑сервер отправляет SIP ACK в браузер.
SIP‑сервер даёт команду RTP/SRTP‑шлюзу установить медиа‑сессию.
Медиа (RTP/SRTP по UDP) передаётся между браузером и RTP‑шлюзом.
Начинается разговор.
3. Завершение звонка
Оператор нажимает «Завершить».
Браузер отправляет SIP BYE на SIP‑сервер.
SIP‑сервер отвечает 200 OK.
Передача RTP/SRTP прекращается.
Если тема будет интересна, то далее обсудим схему работы backend'а и варианты развития общей схемы передачи голоса с плюсами, минусами и ограничениями.
В своем канале в Telegram и канале в Max о разработке в стартапах рассказываю еще больше интересного и делюсь опытом, заходите, буду рад!
Спокойных вам релизов и захватывающих решений !
В чём подвох пожизненной гарантии на сайт
Просматривая сайты коллег по опасному бизнесу сайтостроения иногда натыкаюсь на термин «пожизненная гарантия на сайт» и становится дико смешно от этого.
Вообще, сайт сам по себе не ломается. Это или баг, который не нашли при разработке, или влияние внешних сил:
Поменялось API у системы, с которой сайт интегрирован. Гугл почта включила режим паранойя, ЯндексКарты формат запроса, чат гопоты стал хотеть другой прокси-сервер.
И сайт уже работает не так, как задумывалось.Мамкины хакеры поломали. Если во-время обновлять версии безопасности, сайты вполне могут страдать.
Полозушные руки чужих разработчиков ковырялись в коде. Если нет резервных копий или нельзя откатиться по версиям — это печаль.
Проблема с сервером. Закончилось место на диске, не хватает вычислительной мощности, набежали боты, DDoS-атака
Некорректное отображение в версиях браузеров, вышедших после создания сайта. Это бывает редко, однако возможно, что сайт по прошествии нескольких лет может перестать правильно отображаться в браузерах. Браузеры (Гугл Хром, Опера и другие) постоянно совершенствуются, меняются, перестают поддерживать какие-то устаревшие функции и стандарты.
И это всё гарантию никто не включает. Оно и понятно. Предсказать их влияние невозможно, а чинить проблему может быть трудозатратно.
А «пожизненная гарантия» распространяется только на случай, если в процессе эксплуатации сайта будут выявлены ошибки, связанные с разработкой, компания бесплатно исправит их.
ИТОГО. Пожизненная гарантия — полная туфта.
Не играйте в эти игры. Лучше честно сделать договор на техподдержку, где указаны форсмажоры.
Мой тг-канал — Факапы, инсайты, проблемы, взаимоотношения, клиенты, немного юмора.
Спустя почти год работы мой PR приняли в ядро Joomla!

[Тут должна быть победная пляска] Год назад у моих клиентов возникла необходимость во вставке видео в кастомные поля материалов в раздел портфолио. Я начал делать и увидел, что именно стандартное пользовательское поле Media не умеет вставлять в поле ничего, кроме изображений, хотя поле Joomla Form MediaField умеет выбирать и документы (pdf и иже), аудио, видео и даже папки. Я начал работу над тем, чтобы добавить этот функционал в ядро и очень надеялся успеть к Joomla 5.3, которая выходила в апреле. В целом все сделал, сделал PR 25 февраля 2025 года, но PR не приняли, сказав, что это шибко новый функционал и ему будет хорошо в Joomla 6.0.0. Клиентам пришлось использовать медиа-менеджер от JCE, а PR отправился ждать релиза 6.0.0, который выходил осенью. К слову сказать, эта пауза была полезна для него, так как летом, уже неспешно я получал советы по улучшению и в июле всё точно было готово.
Релизный цикл Joomla состоит из нескольких этапов: сначала выходят alpha-версии (до 3х штук), где просто фиксируются накопленные изменения, потом beta, где наступает feature freeze - заморозка новых функций, их нельзя уже добавлять. Дальше только отладка и правки существующих новшеств. У каждого релиза есть 2 релиз-менеджера.
В работе над PR мне помогал все это время Брайан Тиман - ко-фаундер Joomla. К концу июля все было готово, проверено, PR имел 2 необходимых независимых теста. Ждём беты.
Дата беты приходилась на понедельник. Где-то в пятницу днём я отписался в PR и получил совет написать релиз+менеджерам. Как-то удалось найти их в Mattermost, где обитает международное сообщество, но пятница и выходные, а все ж волонтеры и не на зарплате... Моё сообщение прочитали после релиза беты... Сказали, что не были в курсе моего PR (ожидаемо, их около 200-250 все время открытых). И сказали, что поезд ушёл, хоть и so sorry. Зато будет хорошо увидеть PR на тестах в Pizza, Bugz and Fun и вообще welcome в 6.1.
После выхода 6.0.0 меняются релиз-менеджеры. Мы списались: да, все хорошо, но нужно кое-что подправить. Тут конец года и закрытие дедлайнов, потом Новый год и весь январь никто толком не работает. Beta для 6.1 выходит 17 февраля. Последняя alpha недели за 3 до этого.
Незадолго до выхода альфы я-таки получаю сообщение, что реализуемый функционал сделан не по "Joomla way" и если код в ядре, то этот код является учебным пособием по тому, как ядро использовать. Резонно. А ещё у релиз-менеджера есть собственные наработки и экспертиза в этой теме и свой медиа-менеджер, в котором он тоже прошел огонь, воду и медные трубы. Согласно Joomla way мне нужно было разделить одно мега-крутое поле на 4 отдельных (картинки, аудио, видео и документы). Я подумал, что требуется сделать 4 плагина вместо одного и сказал, что не успею. Мне ответили, что beta is more important for us и время ещё есть, что мне подскажут и 4 плагина делать не нужно.
Пока суть да дело - время идёт. У меня тоже работа, трое детей, карантины, уроки... Но добить этот PR уже стало делом принципа. Я нашел как нужно было делать, принял несколько правок и пожеланий, потом фиксы code style. Сегодня с утра был последний коммит. Сегодня вечером, 11 февраля 2026 года, PR наконец-то смержен в ядро Joomla.
Эта работа научила меня очень многому. 170 комментариев в conversation на GitHub, несколько отдельных переписок, 1 год на разработку и внедрение простой в целом фичи, "звоночек" в голове: "не забыть, успеть, сделать, найти"...
Сегодня я поднимаю кружку пенного за этот небольшой в целом PR, за этот прошедший год, за Joomla и за Open Source.
https://github.com/joomla/joomla-cms/pull/45013
#joomla #cms #opensource #community #webdev
P.S. Фото с пивом сюда выставлять не буду, но представьте, что оно тут есть.
ИИ в техподдержке SpaceWeb решает каждый четвертый запрос

В SpaceWeb ИИ-ассистент стал полноценным инструментом для работы с запросами веб-разработчиков. Сегодня нейросеть полностью закрывает 23,5% обращений пользователей, а ещё в 64% случаев помогает специалистам поддержки формировать ответы.
ИИ берет на себя типовые задачи, с которыми разработчики сталкиваются при запуске и сопровождении сайтов: подключение доменов и SSL, установка CMS, настройка почты, работа в панели управления. Среднее время ответа — около 30 секунд вместо 10–15 минут у человека. В месяц бот самостоятельно обрабатывает более 1200 запросов.
За счет этого нагрузка на сотрудников поддержки снизилась на 9,5%, а эксперты смогли сосредоточиться на сложных и нестандартных кейсах. Для дообучения модели используется обратная связь от пользователей — ответы ИИ можно оценивать лайками.
Как именно устроена работа ИИ-ассистента, какие сценарии он закрывает уже сейчас и зачем SpaceWeb внедрял нейросеть в поддержку — читайте на сайте.
Представлен открытый проект PeerWeb — децентрализованного веб‑хостинга на базе WebTorrent. Решение обеспечивает децентрализованный, устойчивый к цензуре веб‑хостинг через пиринговые сети. «Загружайте свои статические веб‑сайты и делитесь ими по всему миру, не полагаясь на централизованные серверы и не оплачивая хостинг», — пояснили авторы решения.

Selectel открыл первую часть курса по JavaScript

Привет, Хабр! Новичкам бывает трудно сделать первый шаг в программировании. В интернете много сомнительных курсов, а качественные требуют финансовых вложений и несколько месяцев на изучение.
Мы в Selectel подготовили бесплатный курс, который поможет быстро и без лишних затрат изучить основы JavaScript. В первую часть входят три модуля. Вы узнаете:
для чего разработчики используют JavaScript,
как работать с со скриптами, веб-страницами и переменными,
как создать рабочее окружение на IT-инфраструктуре Selectel.
Участники курса смогут бесплатно протестировать сервисы Selectel, а по итогам тестирования — получить сертификат о прохождении.
Событие Pizza, Bugs & Fun - 29-30 января 2026 года.

Уже несколько лет в мире Joomla проводятся мероприятия "Pizza, Bugs & Fun" (#PBF), где каждый может посвятить несколько часов своего мозгового времени тому, чтобы наша любимая CMS стала ближе к идеалу.
Ссылки на видео и статьи из этого поста рассказывает об организационных вопросах, которые пригодятся для участия в PBF, а так же что и как делать. Координация международного сообщества Joomla происходит в Mattermost (присоединиться).
В рамках события PBF все желающие могут собираться в общий онлайн чат, обсудить вопросы Joomla и приложить к их разрешению свою руку. Самый классный вариант, когда эта встреча происходит оффлайн: тогда организовывается пицца, напитки по вкусу и несколько часов совместного творчества.
Каждый помогает тем, что он умеет:
кто-то пишет недостающую документацию,
кто-то пишет код,
кто-то тестирует как исправлены ошибки или сделан новый функционал.
На сайте события есть карта, можно "захостить" свою локацию. Практически все движки в мире развиваются за счёт спонсирующих их компаний. Joomla одна из немногих, где развитие идёт только усилиями международного сообщества энтузиастов.
На момент написания данного поста в репозитории Joomla 810 открытых Issue (как правило это баги) и 236 Pull request (PR, исправление багов и новый функционал). Все PR обязательно тестируются минимум двумя участниками сообщества, дабы в конечный код движка не проскочила ошибка.
Если каждый из участников только нашего сообщества сделает даже одно тестирование, то, боюсь, PR и Issue на всех не хватит 😀 И ничего не останется нашим коллегам из международных Joomla-чатов.
Как тестировать Joomla PHP-разработчику? Компонент Patch tester. (кстати, не только PHP разработчику)
Пост о наболевшем. Clawd и как же им пользоваться.
В общем два дня уже потратил на то чтобы развернуть Clawd bot, естественно в бесплатном формате, по началу шло все хорошо, развернул бота на локальном компе Linux Mint 22.2, создал бота в Телеграмме, привязал к нему Clawdbot.
Так как у clawd нет своей нейронки, ему нужно прикрутить свои мозги. Сначала запросил API ключ в Gemini. Обычная модель, даже самая простая не запускалась. Затем тыкнул в Google Antigravity, который как оказалось имитирует думающую модель Claude 4.5 пуская один и тот же запрос в себя по кругу. Эта штука быстро отвалилось, но успел немного поразвлекаться с ней.
Перебрал половину представленных в списке Clawd моделей, например тот же Deepseek дает API только разработчикам, но в него можно получить доступ через такие сервисы (из списка Clawd), как Openrouter. Openrouter в свою очередь выдал ключ, но выбирая из списка модели, даже с пометкой free ничего не взлетало. На этом я уже устал если честно, поэтому обращаюсь к хабру, дабы развернуть актуальную дискусиию, может накидаете вариантов решения или альтернатив Clawd, а то уж очень захотелось поиграть в агента.
Успел спросить у него, с мозгом Google Antigravity, что он может:
🔧 Код и файлы
— Читать, писать, редактировать код и документы
— Запускать команды в терминале, работать с git🌐 Интернет
— Искать в вебе, парсить страницы
— Управлять браузером (автоматизация, скрейпинг)📅 Организация
— Напоминания и cron-задачи
— Вести заметки, память между сессиями💬 Коммуникация
— Telegram (вот тут и сидим), можно подключить другие каналы
— Могу отправлять сообщения, реагировать🏠 Умный дом / устройства
— Если подключишь ноды — камеры, уведомления на телефон🤖 Сложные задачи
— Могу запускать саб-агентов на длинные задачи в фонеПо сути — твой персональный ассистент-разработчик, который живёт в терминале и мессенджерах.
И соответсвенно мой список вопросов:
Стоит ли брать платную модель? И какую брать если, уж брать?
Насколько я понимаю штука супер небезопасная, а если запускать из песочницы, то все равно прийдется давать какие-то доступы?
Какие есть альтернативы? Уж очень понравился способ взаимодействия через ТГ
Ближайшие события
Представлен открытый веб-редактор изображений DPaint.js (онлайн-версия) на JavaScript, созданный по образцу легендарного Deluxe Paint, с упором на ретро-форматы файлов Amiga. Помимо современных форматов изображений, DPaint.js может читать и записывать файлы иконок Amiga и изображения IFF ILBM.
Основные возможности проекта: слои, выделение, маскирование, инструменты трансформации, эффекты и фильтры, множественная отмена/повтор действий, копирование/вставка из любой другой программы обработки изображений или источника изображений, настраиваемые инструменты дизеринга и циклическая смена цветов.

Коллеги привет, искал себе решение как реагировать на изменения в объекте и нашел отличный сервис, который используется внутри директив таких как NgClass и NgStyle.
KeyValueDiffers позволяет создать KeyValueDiffer для сравнения изменений текущих пар ключ-значение с новыми. Если вы используете иммутабельные объекты, то можно просто обернуть все в эффект, ну а если вы наследники крутого легаси, где все объекты мутируются по ссылке, тогда проверку нужно вешать в DoCheck, чтобы реагировать на каждый тик change detection.
Накидал оба примера, чтобы поделиться с вами:
Иммутабельный с effect:
@Component({
selector: 'app-test',
template: ''
})
export class TestComponent {
public state = input.required<Record<string, string | number>>();
private differs = inject(KeyValueDiffers);
private differ: KeyValueDiffer<string, string | number> | undefined;
constructor() {
effect(() => {
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) => {
console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`)
});
changes.forEachChangedItem((record) => {
console.log(`Изменено: ${record.key} | Новое значение: ${record.currentValue}`)
});
changes.forEachRemovedItem((record) => {
console.log(`Удалено: ${record.key}`)
});
// Остальные методы forEachItem и forEachPreviousItem по необходимости
}
})
}
}
Легаси подход, которого, надеюсь, ни у кого нет, но на всякий случай :)
@Component({
selector: 'app-legacy',
template: ''
})
export class LegacyComponent implements OnInit, DoCheck {
@Input({ required: true }) state!: Record<string, string | number>;
private differs = inject(KeyValueDiffers);
private differ: KeyValueDiffer<string, string | number> | 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) => {
console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`)
});
changes.forEachChangedItem((record) => {
console.log(`Значение изменилось: ${record.key}`)
});
changes.forEachRemovedItem((record) => {
console.log(`Запись удалена: ${record.key}`)
});
// Остальные методы forEachItem и forEachPreviousItem по необходимости
}
}
}
Онлайн сервис проверки конфига nginx на безопасность (Gixy-Next)
На Хабре уже упоминался Gixy как средство проверки безопасности\хардеринга nginx (статья раз, статья два). Недавно появился ещё один проект, основанный на форке Gixy: Gixy-Next (репозиторий, сайт проекта). Из интересного: прямо на сайте есть возможность проверить конфиг nginx (если по какой-то причине не хочется устанавливать приложение). В тексте найденных проблем - ссылки на страницы с подробным описанием типа ошибки.

Решил сегодня почитать, что пишут в Ангуляр комьюнити Хабра, и увидел сильно популярный пост с аж 51 лайком и 71 закладкой.
Начал читать и был удивлен примерами. Автор с уверенностью говорит, как писать на Ангуляр грамотно, и при этом приводит плохие практики в качестве примеров. Я дошел до примера с RxJS, который меня немного триггернул.
Не буду разбирать все кейсы указанные в данном посте, покажу лишь самый плохой пример который меня немного тригернул:
Автор условно говорит, что у нас есть плохой пример использования:
this.http.get('/api/data').subscribe((data) =>; {
this.data = data; // Что если запрос не вернётся?
});и затем приводит хороший пример с сигналами и RxJs:
readonly data = signal([]);
readonly error = signal(null);
loadData() {
this.http.get('/api/data').pipe(
tap(() =>; this.error.set(null)), // Сбрасываем предыдущую ошибку перед загрузкой
catchError((err) =>; {
this.error.set('Не удалось загрузить данные');
return of([]); // Возвращаем пустой массив, чтобы поток не прерывался
})
).subscribe((result) =>; {
this.data.set(result);
});
}я даже не буду указывать на количество антипатернов и плохих практик в данном примере, я просто покажу правильный пример с сигналами и RxJs:
interface State<T = object> {
data: T[];
error: string | null;
}
@Component({...})
export class BestRxJs {
private http = inject(HttpClient);
private loadDataAction$ = new Subject<void>();
private state$ = this.loadDataAction$.pipe(
switchMap(() =>
this.http.get<State[]>('/api/data').pipe(
map((result) => ({ data: result, error: null })),
catchError(() => of({ data: [], error: 'Не удалось загрузить данные' })),
startWith({ data: [], error: null })
)
),
shareReplay({ bufferSize: 1, refCount: true })
);
readonly private state = toSignal(this.state$, {
initialValue: { data: [], error: null }
});
readonly protected data = computed(() => this.state().data);
readonly protected error = computed(() => this.state().error);
protected loadData(): void {
this.loadDataAction$.next();
}
}Этот пост для новичков, которые, начитавшись популярных статей, могут начать применять вредные практики.
Почему стоит использовать protected в Angular компонентах?
Если вы используете в своих компонентах только public и private, вы упускаете возможность сделать архитектуру чище. Я предлагаю четко разделять ответственность членов класса.
Часто мы по инерции делаем public любые методы и свойства, которые нужны в шаблоне (HTML). Но public в TypeScript означает, что это публичный API компонента - к этим методам может получить доступ любой родительский компонент через @ViewChild.
Почему стоит использовать protected:
1. Явное намерение: protected сигнализирует, что метод предназначен для использования внутри класса или в его шаблоне, но не должен вызываться извне.
2. Защита от регрессии: Если другой разработчик попытается вызвать такой метод через @ViewChild, TypeScript выдаст ошибку. Это заставит его задуматься: «Действительно ли мне нужно делать этот метод публичным?» или «Может, стоит создать отдельный метод для API?».
3. Читаемость: Открывая код, вы сразу видите: public - для внешнего мира, protected - для шаблона, private - для внутренней логики сервисов и подписок.
Разделяйте Public API и внутреннюю логику шаблона - ваш код станет надежнее и понятнее.
@Component({
selector: 'app-user-profile',
template: `
<!-- В шаблоне мы без проблем обращаемся к protected свойствам -->
<div class="card">
<h3>{{ userName() }}</h3>
<button (click)="onUpdateClick()">Обновить</button>
@if(isLoading()) {
<div>Загрузка...</div>
}
</div>
`
})
export class UserProfileComponent {
// PRIVATE: Внутренняя логика.
// Не доступно ни в шаблоне, ни родительскому компоненту.
private _userId = 123;
// PROTECTED: Доступно только внутри класса и в ШАБЛОНЕ.
// Идеально для переменных состояния UI и обработчиков событий.
protected userName = signal('Алексей');
protected isLoading = signal(false);
protected onUpdateClick(): void {
this.logAction();
console.log('Кнопку нажали в шаблоне');
}
// PUBLIC: Публичный API компонента.
// Только эти методы мы разрешаем вызывать родительскому компоненту.
public resetState(): void {
this.userName.set('Гость');
this.isLoading.set(false);
}
private logAction(): void {
console.log(`Action logged for userId: ${this._userId}`);
}
}Представлен открытый проект на Python под названием Reverse API engineer. Это консольный инструмент, который фиксирует трафик браузера и автоматически генерирует готовые к работе клиенты Python API. Больше никакого ручного реверс‑инжиниринга — просто просматривайте, записывайте и получайте чистый API‑код.
«Этот инструмент выполняет код локально, используя Claude Code‑ пожалуйста, следите за выводом/ На некоторых веб‑сайтах используется расширенная система обнаружения ботов, которая может ограничивать захват или требовать ручного взаимодействия», — пояснил автор проекта.
Особенности Reverse API:
автоматизация браузера: создан на базе Playground с режимом скрытности для реалистичного просмотра;
режим автономного агента: полностью автоматизированное взаимодействие с браузером с помощью агентов искусственного интеллекта (автоматический режим с MCP, использование браузера, stagehand);
запись HAR: фиксирует весь сетевой трафик в архивном формате HTTP;
генерация на основе искусственного интеллекта: использует Claude 4.5 для анализа трафика и генерации чистого кода на Python;
поддержка нескольких SDK: встроенная интеграция с Claude и OpenCode SDK;
интерактивный интерфейс командной строки: минималистичный интерфейс терминала с переключением режимов (Shift+Tab);
готовность к работе: сгенерированные скрипты содержат обработку ошибок, подсказки по вводу текста и документацию;
история сеансов: все запуски сохраняются локально с полными журналами сообщений;
отслеживание затрат: подробное использование токенов и оценка затрат с поддержкой кэширования.

Как тестировать Joomla PHP-разработчику? Компонент Patch tester.
Joomla - open source PHP-фреймворк с готовой админкой. Его основная разработка ведётся на GitHub. Для того, чтобы международному сообществу разработчиков было удобнее тестировать Pull Requests был создан компонент Patch Tester, который позволяет "накатить" на текущую установку Joomla именно те изменения, которые необходимо протестировать.
На стороне инфраструктуры Joomla для каждого PR собираются готовые пакеты, в которых находится ядро + предложенные изменения. В каждом PR обычно находятся инструкции по тестированию: куда зайти, что нажать, ожидаемый результат. Тестировщики могут предположить дополнительные сценарии, исходя из своего опыта и найти баги, о которых сообщить разработчику. Или не найти, и тогда улучшение или исправление ошибки быстрее войдёт в ядро Joomla.
Напомню, что для того, чтобы PR вошёл в ядро Joomla нужны минимум 2 положительных теста от 2 участников сообщества, кроме автора.
Это видео также на:
Чат русскоязычного Joomla-сообщества
#joomla #php #webdev #community
