NG Stream
248 subscribers
85 photos
4 videos
2 files
465 links
Авторский канал об Angular и новостях фронтенда. Мы рассказываем о том, с чем сталкиваемся в процессе разработки, делимся полезными, на наш взгляд, статьями.

Made by devs for 🅰️ devs

Авторы:
- @antoonG
- @basters

Чат: https://t.me/+JYGeE7HekO04Y2My
Download Telegram
Полезное для Angular

Интерфейс NgZoneOptions включает в себя два параметра eventCoalescing и runCoalescing.

Оказывается, параметры давно присутствуют в фреймворке. Просто лично мне не приходилось применять.

А вот с 18 версии первый из них включен по умолчанию provideZoneChangeDetection({ eventCoalescing: true }) , поэтому тоже считаю важным об этом написать.

Event Coalescing - помогает уменьшить количество срабатываний механизма ChangeDetection, объединяя несколько событий и, повышая общую производительность приложения, особенно при частых взаимодействиях с пользователем, таких как клики, ввод текста и т.д. или асинхронных операциях.

В официальной доке приводят такой пример.

<div (click)="doSomething()">
<button (click)="doSomethingElse()"></button>
</div>


При срабатывании клика по кнопке, затем срабатывает клик по div элементу (event bubbling). ZoneJS перехватывает события, запускает CD, который срабатывает дважды. А с 19 версии, при включенном параметре, будет только один вызов механизма.

Run Coalescing - объединяет несколько запусков NgZone в один, что также оптимизирует процесс обнаружения изменений.

#angular

Подписывайся / Чат
🔥6👍2
На MDN опубликовали статью о Temporal. Постоянные читатели канала могли заметить, что я не пропускаю новости о данном пропозале.

Кто не знает, это новый объект для работы с датой, который призван прийти на замену Date и решить большинство неудобств при работе с временем и часовыми поясами, конвертацией, нахождением разницы между датами и тд, продолжать можно долго. А пока можно поэкспериментировать и ознакомиться.

На странице пропозала на TC39 можно поиграться прямо в консоли, там включен полифилл.

А вот до полноценной поддержки браузерами далеко. Сейчас впереди всех Firefox, причем Nightly сборка.

#js

Подписывайся / Чат
🔥2
Observable API

Через пару версий в Chrome планируют добавить примитив Observable.

Основная идея пропозала заключается в предоставлении более удобного способа управления данными. Вместо императивного подхода с использованием callback функций, который неудобен при работе с большим количеством асинхронных операций, предлагается использовать Observables. Кроме того, в отличие от Promise, они имеют ряд преимуществ, включая возможность обработки множественных значений, отмену подписки и гибкое управление потоком. В общем, все то, к чему мы привыкли, используя RxJs.

Большим преимуществом нативного Observable является интеграция с EventTarget. Предлагаемый метод when(), который возвращает Observable, является заменой стандартному addEventListener().

Изначально было предложено добавить метод .on() в EventTarget. Оказалось, что есть риск коллизии имен с существующим (пользовательским) кодом. Поскольку это посчитали значительным, API метод решили переименовать.

Пример работы:

// Filtering and mapping:
element
.when('click')
.filter((e) => e.target.matches('.foo'))
.map((e) => ({ x: e.clientX, y: e.clientY }))
.subscribe({ next: handleClickAtPoint });


Есть вероятность, что обновят DevTools для удобства дебаггинга. Или решат, что существующих инструментов в нем достаточно. Сейчас, по ответам разработчиков, понятно, что разбираться с этим планируют позже.

Пока примитив добавляют в браузерные движки, Deno тоже решил не отставать и тоже реализовать данный API.

Ссылка на спеку и репозиторий для желающих узнать другие детали.

#js

Подписывайся / Чат
🔥6👍2
Type stripping

Вы слышали, что недавно в Node.js появилась возможность запускать TS-файлы при помощи удаления типов (type stripping). Здесь интересно написано, какие проблемы есть в текущем решении, для чего это в принципе нужно и в каком направлении, вероятно, будет развиваться эта фича Node.js.

Если коротко, то сталкивается стабильность ноды и минусы TS в виде отсутствия спеки, отказа от следования semver, вкупе с частыми обновлениями, возможностью встраивания tsconfig.json в проект и его соответствие типу модуля. Кроме того, большой размер tsc также не добавляет плюсов.

Работает следующим образом: в ноду добавляется SWC (написан на Rust) в виде скомпилированного для WASM бинарника. TS файлы прогоняются через SWC и все.

Enum и namespace, при этом, можно использовать, только при включенном флаге —experimental-transform-types. Что, на мой взгляд, хорошо. namespace вообще редко кто использует, а в чем недостатки enum я писал здесь.

Работа еще продолжается, в TS 5.7 был добавлен флаг rewriteRelativeImportExtensions для изменения расширения с .ts на .js, что ускорит генерацию файлов и, как следствие, сборку. А в следующей версии уже добавили erasableSyntaxOnly, который сообщает компилятору о необходимости выключить несовместимые фичи Enum, experimentalDecorators, namespaces, parameter properties

Очень советую к прочтению roadmap.

#typescript

Подписывайся / Чат
👍1
Нововведения 19.2, новые подходы и RFC

httpResource. Пока в статусе experimental.

Self-closing tags. Добавлены схематики, позволяющие произвести миграцию на self-closing tags (даже не знаю, как это нормально перевести, поэтому буду использовать так).

ng generate @angular/core:self-closing-tag


Сейчас команда Angular обновила раздел в документации. Интересно, почему сразу не обновили до selector-less варианта.😅

Исправлен баг при работе с FormRecord. При объявлении формы с non-nullable значениями типы оборачивались в Partial, из-за чего и возникала ошибка.
#angular

И еще кое-что интересное!

В следующей версии готовятся представить two-way binding, который позволит считывать значения с input без использования FormsModule.

Пример:

input [(value)]="name">
<input type="number" [(valueAsNumber)]="age">
<input type="date" [(valueAsDate)]="birthday">
<input type="file" [(files)]="files" />
<input type="checkbox" [(checked)]="isHappy">


Похоже, сигналы дают такую возможность.

Ссылка на МР, рекомендую ознакомиться.

Новые Resource RFC!

На прошлой неделе команда поделилась RFC, которые описывают

- Архитектурный подход
- API

Первый из них о том, что resource рассматривается, как основной примитив для работы с асинхронностью. Как я понял, цель в том, чтобы предложить разработчикам удобный способ интеграции асинхронных данных в синхронную модель UI. Это позволит компонентам иметь возможность показывать состояния загрузки или ошибок до получения данных.

Рассматривают два паттерна, которые позволяют включать асинхронные источники в синхронные реактивные системы с сигналами:

- Resource (явная асинхронность, где ресурсы представляют асинхронные операции и имеют статус загрузки и значение).
- Suspense ("скрытая" асинхронность, когда чтение значений приостанавливается (suspend), пока не станут доступными. Другими словами, "async signals").

Resource призваны дополнить сигналы, расширяя реактивную систему Angular для поддержки асинхронных сценариев.

#angular

Подписывайся / Чат
👍41🎉1
Немного в продолжение темы новых API

Почитав представленные RFC, отметил для себя особо интересные пункты и решил добавить к сообщению следующее:

Suspense паттерн позволяет работать с асинхронными данными в синхронном режиме, будто они уже доступны, несмотря на то, что загрузка в фоновом режиме еще продолжается.

userData: Signal = asyncComputed(async () => fetch(/api/user/${currentUserId()}));

@suspense {
<user-profile [data]="userData()" />
} @fallback {
<loading-spinner />
}


Если данных в сигнале еще нет (не загружены), срабатывает флаг (на самом деле, выбрасывается исключение).
Suspense API отлавливает это состояние и отображает спиннер.
После того, как данные загрузились, флаг меняет состояние, "suspense boundary" повторяет попытку рендеринга и отображает полученные данные.

Нет необходимости писать кучу дополнительных флагов и собственных велосипедов.

Если добавят prefetch стратегии, которые будут подгружать данные перед инициализацией компонента (кнопки, части UI, например, наведение указателем мыши пользователя на ссылку, прокрутка области просмотра), это привнесет существенное улучшение DX.

Есть и недостатки. Не всегда может быть очевидно, почему часть приложения не загрузилась или UI выглядит не так, как нужно. С отладкой тоже пока непонятно. Dev tools планируют обновить, но гораздо позже.

httpResource

Судя по RFC, это обертка над httpClient, захватывает весь HTTP-стек Angular, включая интерсепторы и утилиты тестирования. Есть отличия:

- запрос инициируется сразу, подписка не нужна.
- интегрирован с сигналами. Если исходный сигнал изменяется, будет сделан новый HTTP-запрос.
- возвращает экземпляр HttpResourceRef, который содержит дополнительные данные.

Пример конфигурации:

results = httpResource({
url: '/api/query',
method: 'POST',
body: {...},
params: {
'rowLimit': 100,
},
});


Одна из целей httpResource - улучшение типо-безопасности. По умолчанию возвращается "raw type", для JSON unknown, для остальных возвращается объектный тип с указанием Blob, string и тд. Что более интересно, планируется добавить функцию parse, позволяющую преобразовать значение в любой тип, добавив валидацию.

Пример интеграции с Zod:

const User = zod.object({
id: zod.number(),
name: zod.string(),
// ... other fields ...
});

const user = httpResource(..., {parse: User.parse});


Планы у команды Angular грандиозные, пока можно изучить планируемые обновления. Ссылки я скинул в предыдущем сообщении:)

#angular

Подписывайся / Чат
👍4
Следующее обновление, похоже, будет дополнено еще одной фичей!

Ближе к выходным опубликовали МР с улучшенной поддержкой TS для свойства host.

Исторически, значения и так были типизированы при использовании с декоратороми @HostBinding(), @HostListener(). Но иногда все же возникали баги с проверкой типов в директивах. Эти проблемы сейчас и решают. И настойчиво рекомендуют переходить c декораторов на свойство host, поскольку именно этот вариант будет исправляться и поддерживаться.

Тем временем, в комментах уже спрашивают про поддержку Tailwind:)

#angular

Подписывайся / Чат
👍2
Инициатива Interop

📌 Для тех, кто не слышал, что это.
Это совместная работа крупнейших команд разработчиков браузеров (Google Chrome, Mozilla Firefox, Microsoft Edge и Apple Safari) для согласованной разработки фич, чтобы стандарты быстрее распространялись и получали стабильную кроссбраузерную поддержку.

Например, одним из предыдущих достижений является обеспечение поддержки современных спецификаций CSS и HTML. Одна из целей инициативы состояла в улучшении совместимости CSS-свойства gap для Flexbox и Grid Layout, которое теперь корректно работает.

📌 В феврале были анонсированы фичи для проработки в этом году. Вот некоторые из них: новые методы для WASM, Storage Access API, URLPattern, Anchor positioning.

📌 Для Storage Access API планируют добавить document.requestStorageAccess(), который повзоляет содержимому iframe запрашивать разрешение на хранение и чтение файлов cookie и других данных сайта. И document.hasStorageAccess(), который, соответсвенно, проверяет, предоставлено ли разрешение.

📌 Что касается WASM, то упоминаются два улучшения:
- Resizable Buffers (позволяют динамически изменять размер памяти, выделенной для модуля WebAssembly, прямо во время выполнения программы, что полезно для оптимизации использования памяти и повышения производительности приложений, работающих с большими объемами данных).
- JS String Built-ins (помогают преобразовывать данные между форматом WASM и привычными строковыми типами JS).

📌 Кроме того, продолжают работу над улучшением совместимости обработки MouseEvent в Safari. Да, наконец-то!!! Стоит сказать, что в прошлом году Safari значительно улучшил поддержку.

📌 Помимо основных целей, есть исследовательские направления:
- Доступность: создать еще больше тестов для обеспечения лучшего уровня доступности.
- WebVTT: направлено на улучшение синхронизированных текстовых треков для субтитров.
- Конфиденциальность: изучение того, какие стандартные функции требуют проработки.

В 2025 основными направлениями инициативы являются обеспечение одинакового поведения CSS, улучшение конфиденциальности с помощью Storage Access API (но, пока отсутствует хорошая автоматизированная система тестирования для проверки конфиденциальности в разных браузерах) и улучшение доступности(a11y).

Подписывайся / Чат
👍5
Все наверняка слышали о портировании компилятора Typescript на Go. В результате чего планируется ускорение сборки проекта в 10 раз. Считаю важным тоже об этом написать и собрать источники в одном посте.

Почувствовать столь существенный прирост возможно будет в 7 версии.

Что необходимо мигрировать?

📌 CLI компилятора
📌 Language server (причем новый будет поддерживать LSP для упрощения работы редакторов кода)
📌 Тулинг, необходимый для работы TS.

Важно отметить, что это портирование на Go, а не переписывание. Код будет скопирован и адаптирован, а не полностью написан с нуля. Что положительно повлияет на время разработки, стабильность, дальнейшую поддержку и консистентность кодовой базы.

В комментариях на github и, в целом, по интернету много срача и вопросов, почему Go. Судя по ответам, дело в производительности, кроссплатформенности и на него лучше всего ложится текущий код TS, который содержит огромное количество рекурсивных данных. И немаловажный фактор - популярность в сообществе веб-разработчиков.

Достижения такого прироста производительности ожидают за счет многопоточности и оптимизации процессов при компиляции. Здесь чуть подробнее. Но остается вопрос, насколько будет расходиться кодовая база с добавлением многопоточности.

Очень многообещающий анонс с далеко идущими перспективами.

Репозиторий с обсуждением.
Статья

#typescript

NgStream / Чат
👍1
Недавно побывал в Питерском музее Яндекса. Это восторг! Опишу пару экспонатов.

ZX Spectrum - про него точно слышали все! Разработан британской Sinclair Research в 1982, стал культовым в Великобритании и странах Восточной Европы из-за низкой цены и высокой доступности. Он обладал простым интерфейсом и базовыми возможностями программирования

Микроша – советский ПК, созданный в начале 80-х на базе TRS-80 Model I, но адаптирован под советское производство. Был популярен среди программистов, благодаря надежности и простоте. И обратите внимание на названия моделей!

Агат – первый советский ПК для массового использования, выпущен в 70-х и использовался в школах, НИИ. Его существенный плюс - поддержка работы с дисками (большинство были с кассетами для хранения данных).

Круто, что компания собрала столько устройств и показала желающим. Представлены игровые консоли, мониторы, книги, методички для разработки ПО! Определенно, плюс для бренда! Советую всем, кто еще не был, посетить!)

NgStream / Чат
👍21🔥1
Изменения в 20 версии

📌 Планируется добавить поддержку two-way-binding для динамически-создаваемых компонентов. Пример из МР:

createComponent(MyCheckbox, {
bindings: [
twoWayBinding('value', value),
],
});


📌 Команда Angular опубликовала МР, где привычные директивы *ngFor, *ngIf помечены deprecated. Ожидаемый переход в сторону более гибкого control flow, анонсированного в 17 версии.
Автоматическая миграция будет произведена при обновлении через ng update.

Важное замечание, что это касается не всех структурных директив, а только указанных.

Если вы еще думаете, переходить или нет, то вот пара очевидных плюсов:
- использование обоих подходов влияет на размер бандла, т.к. задействованы обе реализации.
- новый подход положительно влияет на производительность, поскольку реализует новый reconciliation алгоритм. Расчеты можно посмотреть тут.

#angular

NgStream / Чат
🔥4
В предстоящем обновлении на 20 версию в Angular CLI будет удален тип из имен файлов и имен классов (суффикс) для компонентов, директив и сервисов.
Теперь, добавленные при помощи CLI компоненты, будут выглядеть так:

ng generate component user

user.css
user.ts
user.ng.html


Это будет сделано, согласно обновленному style guide. Как пишут сами разработчики:

«Со временем мы заметили, что такое соглашение об именах может сделать инфраструктуру громоздкой и шаблонной, особенно для новых разработчиков, не привыкших к такой практике». И об изменении имен классов: "…имя класса должно отражать поведение и обязанности класса, а не то, как он используется. Термин «сервис», в частности, не добавляет какой-либо значимой информации для объяснения того, что делает класс".

На мой взгляд, наоборот, по названию файла/класса более понятно за что он отвечает. И говорящее имя сущности и тип делают только лучше. И ничего страшного в том, что другие разработчики не привыкли. Используя любой инструмент, необходимо понять принципы его работы и подходы. Если же вам сильно кажется излишним (такие на паре проектов были), то обновите схематик и живите счастливо.

Но, справедливости ради, надо сказать, что такую возможность нам оставляют и сейчас. Можно указать тип создаваемой сущности в строке терминала или сразу в схематике:

ng generate component user --type=Component
ng generate service user --type=Service
ng generate directive user --type=Directive


"@schematics/angular:component": {
"type": "Component"
"ngHtml": false
}


В этом случае, тип сущности останется так, как это выглядит сейчас.

#angular

NgStream / Чат
💯5👍2
Angular code style 2025

Похоже, что guide почти готов и скоро будет опубликован. Разработчики выложили предварительную версию, с которой можно ознакомиться прямо сейчас.

Сразу можно заметить, что документ не фиксирует обязательный свод правил, а представляет набор рекомендаций, которые способствуют согласованности в проектах на Angular. Мы знаем, что предыдущий code style и предлагаемая архитектура являлись одними из плюсов фреймворка.

Также отмечается, что гайд не затрагивает часть с TS. Для этого есть ссылка на Google code style.

Из основного:

📌 Обновленное именование. Отказ от использования component, directive и тд.
📌 One concept per file. Для каждого элемента отдельный файл. Однако, если они небольшие и связаны одной идеей, то нормально написать это в одном.
📌 Рекомендация property injection over class injection. Более читаемый вариант и лучше типизация.
📌 Группировать Angular-specific сущности (inputs, outputs, queries, и injected deps) перед остальными методами.
📌 Избегать сложной логики в шаблонах, т.к. это не всегда очевидно и, определенно усложняет чтение кода и рефакторинг. Однозначно топ рекомендация! Теперь удобнее будет аргументировать на code review:)
📌 Используйте protected модификатор доступа, если свойство вызывается только в шаблоне.
📌 Рекомендация использовать class and style, а не ngClass and ngStyle.

Это часть изменений, с остальным можно ознакомиться по ссылке. На самом деле, все рекомендации очевидны и объясняются зачастую здравым смыслом. Следуем и делаем наши проекты лучше!

Ссылка на обновленный style guide.

#angular

NgStream / Чат
👍7
В репозитории Anguar заинтересовал один МР об оптимизации конструкции let.

📌 Суть в том, что для корректной работы DI требуется узел дерева (TNode), создаваемый вызовом declareLet. Поскольку необходимость наличия узла возникает тогда, когда используются pipes, теперь выражения без пайпов оптимизируются путём удаления соответствующих операций declareLet. Но здесь не столько оптимизации интересны, а дополнение существующего control flow.

📌 Если что, @let не директива. Как и @if синтаксис, это часть движка шаблонизатора, поэтому он не требует импорта и сразу доступен в шаблоне.

📌 Сама конструкция полезна и давно ожидаема сообществом. Коротко: если требуется переменная в шаблоне, приходится импортировать *ngIf, что выглядит излишне и отличается по семантике. Основное отличие с *ngIf в том, что let не проверяет falsy values, а просто объявляет переменную в шаблоне.

Дело в том, что из-за привязки к control flow реализация отличается от того, что есть, например, в TaigaUI, где это отдельная директива. Как результат, есть вероятность получить такой существенный минус, как размывание логики. Поскольку нет ограничений по использованию, которые накладывает директива, многие станут неоправданно активно применять в шаблоне и получим перегруженный JSX. На мой взгляд, это неправильно. Все же шаблоны это про отображение данных, для написания логики есть контроллеры. Ниже я привел пример чрезмерного использования конструкции, о котором говорю.

@let foo = something$ | async

<div></div>
...
<!-- много верстки -->

@let store = notificationsStore$ | async


📌 Из плюсов, конечно, стоит отметить только улучшенную типизацию. Возможно, есть еще плюсы?

#angular

NgStream / Чат
👍31
Нововведения и ожидания Angular 20

Уже на 29 мая (четверг) в 19:00 MSK анонсирован Angular Developer Event.

🌵 Следующие фичи изменили статус на stable: linkedSignal, withI18nSupport, PendingTasks, afterEveryRender*, afterNextRender, toSignal, toObservable, withIncrementalHydration.

🛠 Помечены как deprecated: ngIf, ngFor, ngSwitch, HammerJS integration, platformServerTesting, ServerTestingModule.

*afterRender переименован в afterEveryRender. Предназначен для выполнения кода после рендеринга всех компонентов на странице.

Добавлена поддержка оператора in в шаблонах. Его работа аналогична in в TS. Проверка, что свойство есть в объекте (не значение свойства).

{{ 'name' in user }}

@if ('name' in user) {}

[disabled]="'name' in user"


Интересно, что в 19 версии была добавлена поддержка typeof в шаблоне, в 20 оператор in. Получается, что команда решила постепенно сокращать расстояние между TS и Angular.

И в конце ссылка на Angular CanIUse. А чего ждете вы от предстоящего релиза?

#angular

NgStream / Чат
❤‍🔥5👍2
В 20 версии linkedSignal() станет stable. Поэтому сегодня посмотрим его отличия от computed().

📌 computed - сигнал, который рассчитывает своё значение на основе зависимых сигналов. Представьте себе реактивную формулу, которая всегда синхронизирована со своими зависимостями.

Основные особенности:
- Readonly: Вы не можете изменить значение.
- Lazily evaluated: Срабатывает при обращении к нему.
- Memoized: Значение закэшировано, пока зависимость не изменится.
- Dynamic dependencies: Отслеживает только то, что необходимо для выполнения.

📌 linkedSignal - writable сигнал, связывает сигналы, обновляет состояние, в зависимости от значений, но сохраняет возможность ручных изменений.

listOfItems = signal(['item1', 'item2', 'item3']);
countOfItems = linkedSignal(() => this.listOfItems().length);


- Writable. Может быть обновлён вручную .set() или .update().
- Reactive. Автоматически обновляется на основе переданных сигналов
- Access to previous values. Доступ к предыдущему значению, полезно для продвинутых механизмов синхронизации состояния.
- No memoization. Всегда рассчитывается повторно, кеш отсутствует.

// Можем сделать вот так
changeTheCountOfItems() {
this.countOfItems.set(0);
}
// Есть еще одна форма записи
const countOfItems = linkedSignal({
source: this.listOfItems,
computation: (items) => items.length,
});


Здесь linkedSignal принимает ссылку на сигнал, и, когда значение изменится, вызовется computation функция. Пример, где пригодилась бы эта функция, есть здесь, можно ознакомиться подробнее. Покажу более простой.

Можно привязать состояние пагинации к строке поиска, обеспечивая синхронный и предсказуемый сброс. Здесь гарантируется, что сброс пагинации произойдет тогда, когда действительно изменится строка ввода.

const search = signal('');
const page = linkedSignal({
source: search,
computation: () => 1,
});


linkedSignal хорошо использовать для синхронных обновлений состояния.

И коротко добавлю еще:

📌 effect - выполняется асинхронно, планируется и разрешается фреймворком, поэтому конкретное время для выполнения не определено. Предназначен для side-effects, например, для логирования, выполнения API запросов. Не для обновления других сигналов, это может привести с цикличным перерасчетам.

📌 untracked - позволяет сделать сигнал неотслеживаемым внутри определённого контекста выполнения. То есть даже если сигнал меняется, контекст всё равно не будет уведомляться, однако будет иметь доступ к актуальному значению. Может быть использован для изменения состояния сигнала внутри effect(), но делать это не рекомендуется.

#angular

NgStream / Чат
🔥6🤪2👍1
Microsoft анонсировала TypeScript Native Previews. Это история, которую они сообщили в марте о портировании компилятора на Go.

Теперь команда разработчиков говорит о промежуточных результатах, в частности, за счет быстрой работы Go и использования параллельных вычислений существенно возросла скорость инкрементальной сборки и IntelliSense.

Попробовать можно уже сейчас:

npm install -D @typescript/native-preview

// Включить нативный режим в VS Code "typescript.tsserver.useNativeWatcher": true

npx tsgo --project ./src/tsconfig.json


Позже планируют заменить tsgo на tsc и эта реализация станет стандартом, заменяя текущую Node.js-реализацию.

Мне кажется, что VS Code получит самый большой буст, особенно с автокомплитом, потому что идет работа над улучшением language server, переходу с TSServer на LSP. Обещают в этом году показать более полную версию, включая улучшенную работу в редакторах. Первые сборки будут после релиза 7 версии.

#typescript

NgStream / Чат
❤‍🔥2👍2
Как замерить developer experience для разработчиков

Некоторое время назад решил сформулировать, как замерить DX? На основе каких параметров мы можем, насколько это возможно точно сделать замеры.

Опросы и обратная связь для получения объективной картины?🤔 Может быть весьма сомнительно. Вопросы касательно удобства инструментов, документации, скорости развертывания, на мой взгляд, не покажут картину целиком, ну или составить будет весьма сложно.

Команда DevOps Research and Assessment (DORA) из Google Cloud придумали 4 главные метрики разработки. Если коротко, это термометр, который показывает, где всё 🔥, а где ещё можно подкрутить.

📌 Lead Time for Changes (LTFC): Время от внесения изменения в код до релиза.
📌 Deployment Frequency (DF): Как часто релизим.
📌 Mean Time to Restore (MTTR): Среднее время восстановления системы после сбоя.
📌 Change Failure Rate (CFR): Количество багов на релиз.

Эти метрики помогают оценить зрелость и эффективность DevOps практик в команде. Недавно добавили еще одну Reliability, но это лежит в плоскости operational excellence.

Так в чем связь?

1. Улучшение LTFC. При работе в среде с отличным DX, можно быстрее внедрять изменения, благодаря настроенным инструментам и процессам. Это сокращает LTFC, т.к. вы разработатываете приложение, а не тратите время на настройку окружения и борьбу с инфраструктурой.
2. Частота развертываний (DF). Если мы уверены в способности быстро и надежно релизить, частота развертываний увеличивается (кэп). Автотесты, стабильный CI/CD и понятная дока уменьшают страх перед изменениями и позволяют команде/компании чаще выпускать новые фичи. Если еще и работаете по TBD, с фича-флагами, то вообще песня:)
3. Быстрое восстановление (MTTR). Для этого необходимо наличие инструментов мониторинга и диагностики, чтобы быстрее выявлять и устранять инциденты. Описанные процессы по устранению и реагированию тоже дадут плюс. Но это можно отнести к пункту про хорошую документацию.
4. Низкий CFR. Автотесты, тщательная проверка кода и ясность процессов минимизируют риски ошибок.

Метрики подобраны таким образом, чтобы их было сложно накрутить, т.е., по сути, каждая команда вынуждена искать какое-то оптимальное значение для себя. Например, если без изменения процессов просто начать релизить каждый коммит в продакшен, то deployment frequency увеличится. Супер, мы улучшили метрику! Но без хорошо построенных процессов тестирования, скорее всего, сильно просядет change fail rate.

У ребят много интересных материалов:
- Тест, насколько команда перформит круче других.
- Подробнее о метриках
- Как влиять на каждую из метрик.

#нетехзаметки

NgStream / Чат
👏2👍1
На прошлой неделе представили Angular 20

Я заработался и только на выходных познакомился с обновлением. Поэтому кратко для тех, кто еще не в курсе изменений.

📌 На презентации много говорили об httpResource. Это, по сути, обертка над httpClient, но с сигналами. Еще в experimental, поэтому пока не рекомендуется к использованию.

📌 SSR. Incremental Hydration в статусе stable. Очень мощный инструмент, позволяющий через Control flow задавать логику для гидрации элемента на странице. Ниже пример с defer, а в разделе на сайте написано подробнее.

@defer (hydrate on <<trigger>>) {
<deferred-component />
}


📌 Динамическое создание компонентов. Функция createComponent позволяет делать это с меньшим количеством действий. В параметрах указывается сам компонент, привычные input/output, даже директивы.

createComponent(MyDialog, {
bindings: [
// Bind a signal to the `canClose` input.
inputBinding('canClose', canClose),
outputBinding<Result>('onClose', result => {}),
twoWayBinding('title', title),
],
directives: [
FocusTrap,
{
type: HasColor,
bindings: [inputBinding('color', () => 'red')]
}
]
});


📌 Добавлена возможность использовать:
- оператор in в шаблоне
- untagged template literals. Что особенно удобно для кастомизации и работы с классами.

<div [class]="`layout col-${colWidth}`"></div>


📌 Помечены как deprecated: ngIf, ngFor, ngSwitch, HammerJS integration, platformServerTesting, ServerTestingModule.

📌 Обновили генерацию элементов через CLI после изменений в style guide. Теперь при создании нового проекта не будут добавляться суффиксы для компонентов, директив, pipes и сервисов. Для существующих проектов генерация будет включена в angular.json.

📌 Добавили инструменты и примеры для интеграции AI. Теперь можно легко подключать LLM, такие как Gemini, OpenAI, Anthropic и другие для создания функций вроде чата, генерации текстов, анализа изображений, рекомендаций и т.д.

📌 Также добавили, что стоит двигаться в сторону zoneless приложений. Через пару версий, мне кажется, сделают stable. А пока стоит провести предварительную работу, если еще не сделали. А именно, перевести компоненты на OnPush, уходить от модулей (по крайней мере, новые части кода писать на standalone). Кто не знал, zone.js довольная тяжеловесная библиотека и отказ от нее положительно повлияет на бандл приложения.

📌 Кроме того, проверка производительности будет доступна в chrome dev tools, не нужно скачивать дополнительные расширения! Достаточно обновиться на 20 версию и Chrome 136, вызвать в консоли ng.enableProfiling().

Ну, и на десерт, говорилось о выборе маскотов, показали немного упоротые варианты.😆 В официальном анонсе по ссылке посмотрите, если еще не видели:)

#angular

NgStream / Чат
👍3👏1