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. Рекомендую к прочтению, учитывая, сколько сейчас появилось способов сделать одно и то же разными способами. Почему это плохо, я уже писал в канале. Если подходы все же есть, стоит знать, где и какой применять.

https://www.angularspace.com/angular-friction-points/

#angular
👍7🔥1
Тут Пол Грэм написал заметку с посылом, что отдавая все больше вещей на откуп AI, мы сами можем разучиться ясно мыслить. Он считает очень важным умение писать, качественно выражать свои мысли на бумаге (либо пикселями на экране).

Автор считает, что невозможно научиться ясно выражать свои мысли и думать, без умения изложить их на письме (привет голосовые сообщения? 😅), при этом с развитием генеративных AI люди будут все реже писать что-то сами.

По мнению Пола, через пару десятилетий, мир может разделиться на тех, кто умеет писать и тех, кто не умеет совсем, т.е. исчезнет золотая середина из людей, кто может не идеально, но писать о чем-либо (мысли, статьи, что-то серьезнее).
Он приводит цитату американского ученого компьютерщика и математика Лесли Лэмпорта (Leslie Lamport):
If you're thinking without writing, you only think you're thinking.


В качестве аналогии Пол приводит пример, что в доиндустривальную эпоху большинство людей были сильными благодаря обилию тяжелой работы, которую они выполняли. В современном мире, мы вынуждены ходить в тренажерный зал, чтобы держать свое тело в форме.
So there are still strong people, but only those who choose to be.


Что думаете по этому поводу, господа и госпожи (господыни)?
🔥3👍1
Команда Angular (совместно с авторами Angular Space community) обновят весьма устаревший style guide!

На прошлой неделе RFC (Request For Comments) был опубликован, просмотреть у меня получилось только на выходных.

Я предполагал, что в гайде покажут стиль работы с новыми API, интеграции с RxJS, работу с конвертацией toSignal() / toObservable() и тд. Но для этого придется ждать последующих обновлений.

Из интересного:

📌 Автор в комментах предлагает помечать свойства класса, которые используются только в шаблонах, как protected и уже сейчас переписать тесты, опираясь на это правило.
📌 Добавление типа сущности в имена (component, service, pipe) - от данного подхода RFC предлагает отказаться, что вызвало бурное обсуждение. На мой взгляд, подобное правило приведет к путанице. Данный подход не должен быть регламентирован в официальном style guide, а принят в конкретном проекте командой/техлидом и изменен, если считаете, что это лучше отразит функциональность.
📌 Рекомендация писать отдельный файл для шаблона, если размер превышает несколько строк - будет убрана. И здесь, конечно же, отсылка к распространению JSX. О DevExp команда предпочла здесь забыть…

Что же, ждем. После столь значительных нововведений разработчики должны знать, на что ссылаться, применять на проектах. Ссылка на RFC здесь для вас.

Чат для обсуждений

#angular
🔥6
Для тех, кто еще не знает, анонсирован Angular Developer Event, на котором состоится выход 19 версии.

В вторник 19 ноября в 20:00 MSK. На скрине дата неправильная.

А чего бы вы хотели увидеть в новой версии?

На мой взгляд, эта версия скорее минорная. Из основного:

📌 Выход из dev preview многих фичей.
📌 Resource API. Experimental mode. В целом, сомнительный подход.
📌 Incremental hydration.
📌 Улучшение HMR (кто не знает, это обновление шаблонов, стилей без полной перезагрузки приложения).

Мне кажется, что переписывание Forms API на сигналы было бы куда интереснее. Но, в настоящее время, команда Angular только определила основные ограничения и находится в состоянии обсуждения возможных изменений. После чего планирует поделиться с сообществом конкретными предложениями в форме RFC.

#angular
🔥5👍2
Что с ресурсами?

Попробую в заметке выяснить, что это и коротко подчеркнуть плюсы/минусы, которые вижу я.

Ресурс состоит из функции loader(), возвращающей Promise и опционального сигнала. Функция срабатывает при инициализации ресурса и при изменении параметров сигнала.

cities = resource({
request: () => ({ id: this.id() }),
loader: (param) => {
return this.service.findCity(param.request);
}
});


Новое API:
📌 обладает семантикой switchMap. Другими словами, предыдущие запросы будут отклонены и возвращены последние запрашиваемые данные.
📌 позволяет удобно обрабатывать ошибки и состояние загрузки. Можно просто обратиться к ресурсу и получить состояние.

this.cities.isLoading;
this.cities.error;


📌 присутствует совместимость с RxJS.

Преимущества
1. Позволяет легко управлять состоянием загрузки, успешного завершения и ошибок без необходимости писать собственные велосипеды.
2. Возможная интеграция с Angular Forms. Это было бы круто связать данные между формами и асинхронными источниками. Есть в сети примеры с linkedSignal и формами.
3. Кэширование данных, что может значительно повысить производительность приложения, уменьшая количество запросов к серверу.

// EditUserComponent
userId = input<string>();
userRes = rxResource({
request: () => ({ id: this.userId() }),
loader: (param) => this.service.getUser(param.id);
})
form = {
name: linkedSignal(() => this.userRes.value().name),
email: linkedSignal(() => this.userRes.value().email)
};


Недостатки
📌 Снова получаем 1000 и 1 способ сделать одно и то же.
Противоречие существующему HttpClient. Очень интересно, представят ли в следующих версиях отдельный HttpClient с тем же API, но возвращающим Promise?
📌 Будет ли такая гибкость, как у RxJS? Пока что есть ощущение, что придется преобразовывать туда/обратно, что приведет к невообразимому количеству бойлерплейта. Если хотели уменьшить порог входа, то получили пока ровно обратное.
Пример, как на фото в комментариях, лично для меня сложно читаем. Это то, что ждут от Angular сейчас? Чтобы не тратить часы на разбор, цель в примере: получить список городов по запрашиваемому году основания.

Чат для обсуждений

#angular
👍4🤔3
На недавней конференции разработчики Angular говорили о возможном расширении лексического окружения, которое будет распространяться на шаблоны. Примеры того, как это может выглядеть, показаны на скрине.
Это означает, что мы могли бы использовать всё то же, что и в классе компонента, но без необходимости объявлять свойства в классе.

И уже есть МР, добавляющий поддержку глобального this для шаблонов.

Возвращение к AngularJS? Что вы думаете об этом?

И, еще из недавних обновлений, прочитал на выходных, что LinkedSignal все-таки будет в dev preview, (не experimental) в 19 версии.

Чат для обсуждений

#angular
👍6🤔1
Привет!

Мы знаем, что вы до сих пор спите и видите сны на TypeScript! 🌟
Мы прекрасно знаем, как вы любите Angular. Сейчас ещё есть возможность зарегистрироваться на Angular Meetup #23.

Мы будем обсуждать текущее состояние Angular и что нас ждет. Узнаем, сколько версий фреймворка нужно пропустить, чтобы считать свой проект устаревшим. 👩‍💻

В конце нас ждет афтепати в лучших традициях: настолки, задачи на написание кода и неформальный нетворкинг с единомышленниками.

Если ты с нами
1️⃣ Регистрируйся здесь
2️⃣ Добавляй напоминание в календарь
3️⃣ Поделись этим сообщением с друзьями - чем больше нас будет, тем веселее!

Если не получится прийти на митап, можно посмотреть трансляцию онлайн.
🔥4
Angular 19 вышел

Что нового? Я подчеркнул основные фичи, на мой взгляд.

📌 Поддержка TS 5.7
📌 Теперь в статусе stable: takeUntilDestroyed, signal quieries, model, inputs, outputToObservable, outputFromObservable, @let
📌 Добавлены схематики для конвертации @Input , DOM queries на сигнальные.

ng generate @angular/core:signal-input-migration
ng generate @angular/core:signal-queries-migration


📌
Добавлен afterRenderEffect() замещает случаи, где нужно использовать effect(). позволяет создавать эффекты для работы с DOM элементами. При этом Angular будет оптимизировать подобные вызовы.
📌 При обновлении будет автоматическая миграция, в ходе которой удалится флаг standalone: true для существующих standalone сущностей и добавится standalone: false для NgModule. При желании можно включить режим компилятора strictStandalone для генерации только таких компонентов.
📌 Добавлено свойство для обнаружения неиспользуемых импортов standalone сущностей. Опция включается в tsconfig.

{ "angularCompilerOptions": {
"extendedDiagnostics": {
"checks": {
"unusedStandaloneImports": "suppress"
}
}
}
}


📌
Добавлено новое Incremental Hydration API.
📌 Добавлен input в RouterOutlet, который позволит передавать данные из родительского компонента в компоненты вывода. Значение будет доступно для дочерних компонентов через токен ROUTER_OUTLET_DATA.

Подробнее по ссылке

#angular
7👍2
Немного для дизайнеров

Я очень редко публикую какие-либо заметки о дизайне. И сейчас тот самый случай)

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

📌 designsystems.surf - здесь можно найти ссылки на дизайн системы известных компаний. Можно вдохновиться решениями.

📌 component.gallery - посвящен UI компонентам для веба. Тут собраны дизайны из разных UI библиотек. Для тех, кто сейчас проектирует систему, собирает макет и тд может быть весьма полезен. Мне стало интересно, что будет написано о компоненте Popover. На странице указаны рекомендации по реализации, советы в области a11y. Даже показан пример недавно появившегося Popover API.

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

#ux_design
3👍2
Директивы ngStyle and ngClass deprecated!

В 19.1 уже будет рекомендация их не использовать. Вместо этого предлагается биндить значения к встроенным [class] и [style]. Давно собирались это сделать, решили только сейчас, несмотря на то, что фича продолжает довольно широко использоваться в проектах:)

МР содержит заметку с ограничениями, которые есть у нативных способов привязки:

📌 Нет поддержки Set.
📌 Не получится добавить несколько стилей/классов, разделенных пробелом.

Например, вместо подобной записи

<div [ngClass]="{ 'ring ring-pink-500 ring-offset-2 dark:ring-green-500' : condition }">


можно использовать такую:

<div class="{{ condition ? 'ring ring-pink-500 ring-offset-2 dark:ring' : '' }}"></div>

Как обычно, прикрепляю МР с подробностями.

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

Подписывайся / Чат

#angular
4👍2
Обновление безопасности (CSP)

Только сейчас узнал, что еще было добавлено в новой версии! Теперь Angular автоматически будет генерировать hash-based CSP, реализуя строгую политику безопасности. Необходимо добавить параметр в angular.json:

"security": {
"autoCSP": true
}


Hash-based CSP позволяет указывать хеши для каждого встроенного скрипта, что делает их безопасными для выполнения. Это означает, что только скрипты с известными хешами будут выполняться, и злоумышленники не смогут внедрить свой код без соответствующего хеша.

Сегодня вместо того, чтобы предоставлять список разрешений, из которого можно загружать скрипты, рекомендуется использовать строгий CSP, который бывает двух видов: nonce-based и hash-based. Первый требует генерации уникального идентификатора для каждого ответа, CSP на основе хэша - идеальный выбор для статически обслуживаемого контента без рендеринга на стороне сервера (SSR).

Подписывайся / Чат

#angular #js
👍5🔥3
Я решил написать о типах, которые могут помочь в определенной ситуации и позволят не городить лишние велосипеды. Уверен, что многие из подписчиков знают об этом, но не все. А, если у вас есть, что дополнить, особенно преимущества/недостатки, пишите в комментах!

ReturnType<T> — это Utility Type, который извлекает тип из возвращаемого значения любой функции. Может понадобится при работе с библиотекой, которая не экспортирует типы, но которые нам нужны. Другой пример: написание своей утилиты. Ну или какие-либо трудноизвлекаемые типы.

// type Message = Message.TextMessage;
type Message = ReturnType<typeof bot.telegram.sendMessage>

async function getMessage() {
const res = await bot.telegram.sendMessage('Text');
}


В примере выше тип Message будет точным типом, который используется в либе.

Преимущества:
1. Удобство и безопасность: автоматическое извлечение типа возвращаемого значения функции снижает вероятность ошибок и повышает читаемость кода.
2. Сокращение дублирования: не нужно вручную повторять тип возвращаемого значения, что облегчает рефакторинг и поддержку кода.
Есть и очевидный недостаток. Если функция не экспортируется/не видима, воспользоваться типом не получится.

Следующий тип - NoInfer<T> был добавлен относительно недавно - в TS 5.5. Нужен для вывода типов без сравнения с внутренними типами. Покажу на примере.

const list = [1, 2, 3, undefined];

list
.filter((item) => item !== undefined)
.map((item) => {
...
item.toString();
})


Раньше это вызвало бы ошибку, т.к. тип item в map() был number | undefined, не смотря на то, что в этой части кода undefined уже быть не может. В новых версиях данный пример отработает даже без каких-либо действий с нашей стороны. Параметр функции map() уже выведен корректно.

Что мы получаем? Точность типизации, что особенно полезно в сложных сценариях с generic типами.

function createFSM<TState extends string>(config: {
initial: TState;
states: TState[];
}): TState;

const example = createFSM({
initial: "not-allowed",
states: ["open", "closed"],
});

В примере выше TState складывается из возможных значений initial и states: "not-allowed" | "open"| "closed". Но, если мы хотим, чтобы тип initial был взят только из допустимых значений states? В этом случае сработает добавление initial: NoInfer<TState>; Теперь "not-allowed" будет указан, как ошибочный, поскольку не находится в наборе допустимых. Добавляя тип, мы сможем контролировать набор значений, которые TS извлечет из generic типа. Здесь статья с подробными примерами.

#typescript

Подписывайся / Чат
🔥31
Active zone

Новая статья от Саши Инкина - разбор нетривиальной задачи и решения. На первый взгляд, что сложного в управлении кнопкой с выпадающим меню? Однако, по мере реализации, выясняется множество деталей, о которых и пойдет речь.

- Практические примеры из Taiga UI.
- Детальный разбор решения и пограничных случаев.

Подробности - по ссылке.

Подписывайся / Чат

#angular
👍1
JS Import Attributes

Не так давно данный пропозал был включен в стандарт EcmaScript.

В чем суть?

Раньше, при импорте модулей, JS не предоставлял возможности явного указания типа загружаемого ресурса. Это создавало проблемы безопасности и функциональности. Например, можно было случайно или намеренно загрузить файл, как JS модуль, хотя на самом деле это был JSON и т.д. Что в результате могло привести к выполнению нежелательного кода. Может показаться очевидным, что файл, заканчивающийся на .js, будет соответствовать файлу application/javascript. На практике в вебе широко распространено несоответствие между расширением файла и заголовком HTTP Content Type. Здесь описано более детально, можете ознакомиться.

Import Attributes (ранее назывался Import Assertions) позволяет явно указать тип модуля. Если что-то пойдет не так, то вернется ошибка.

Ниже пример использования с импортом JSON. Без with { type: 'json' } файл мог быть интерпретирован как JS, что привело бы к ошибкам. А теперь есть некий контракт между вашим кодом и runtime. Вы явно объявляете, какой тип модуля вы ожидаете:

import json from './data.json' with { type: 'json' };
console.log(json);


Если вы помечаете модуль типом: json, вы гарантированно получите либо данные JSON, либо ошибку, но не исполняемый код.

Преимущества

📌 Безопасность: Предотвращение выполнения некорректного кода.
📌 Явное указание. Повышает читаемость кода. Вне зависимости от контекста считаю плюсом.
📌 Расширяемость: Возможность поддержки новых типов ресурсов в будущем.

Ссылка на детали пропозала.

Подписывайся / Чат

#js
👍4🔥4
Разница SRI и CSP
Недавно писал об улучшении политики безопасности CSP в Angular. И в комментариях получилось обсуждение о его отличиях с SRI. Вот решил чуть подробнее раскрыть тему и лучше разобраться самому.

Subresource Integrity (SRI) – механизм проверки целостности контента при загрузке с сервера. Он позволяет убедиться, что файл не был изменен во время передачи или хранения. Что особенно важно при использовании CDN или других сервисов для загрузки JS, CSS и другой статики.

Как работает SRI? При загрузке ресурса с использованием тега <script> или <link>, указывается хэш-сумма файла в атрибуте integrity. Браузер вычисляет хэш загруженного файла и сравнивает с указанным значением. Если совпадают, ресурс считается безопасным и загружается; если нет – браузер блокирует загрузку. Пример использования SRI:

<script src="https://cock.com/script.js"integrity="sha384-0aJk+WbYjC...WLWHLl" crossorigin="anonymous"></script>


Content Security Policy (CSP) – набор политик безопасности. Это указание браузеру, из каких источников загружать ресурсы (скрипты, шрифты и тд) и запрет на выполнение скриптов (unsafe-inline). CSP указывается в виде http-заголовка или мета-тега и состоит из различных директив, управляющих разрешениями для соответствующих ресурсов / функций браузера. Функции дополнялись в каждой версии, сейчас актуальной является 3. Пример политики CSP:

Content-Security-Policy: default-src 'self'; script-src 'self'; script-src-elem 'self'; style-src 'none'; img-src 'none'; connect-src 'self'; font-src 'none'; object-src 'none'; media-src 'none'; frame-src 'none'; child-src 'none'; form-action 'none'; worker-src 'none'; manifest-src 'none'; navigate-to 'none';


Например, директива connect-src ограничивает, с какими доменами можно устанавливать соединения. Это предотвращает утечку данных через расширения, которые пытаются получить доступ к данным.
Коротко о разнице:

SRI
- Используется для проверки целостности конкретных ресурсов.
- Работает на уровне отдельных ресурсов. Для каждого внешнего файла указывается хэш-сумма, которая проверяется браузером перед загрузкой.
- Применяется только к внешним ресурсам, загружаемым через теги <script> и <link>.
- Требует указания конкретной хэш-суммы для каждого ресурса, что делает его менее гибким при изменении содержимого файлов.

CSP
- Контролирует источники, откуда могут загружаться ресурсы и ограничивает тип контента для выполнения.
- Определяет общие правила для всех ресурсов страницы. Политики применяются ко всем ресурсам определенного типа (скрипты, стили и тд).
- Может применяться ко всему контенту страницы, включая внутренние и внешние ресурсы.
- Позволяет гибко настраивать политику безопасности, например, разрешать загрузку ресурсов с определенных доменов или запрещать определенные типы контента.

Оба инструмента эффективно дополняют друг друга, улучшая безопасность приложения. Механизмы снижают часть рисков и не являются достаточными. Например, CSP является дополнительным способом защиты от XSS, что было сказано в 2 версии спеки. Важно применять комплексный подход к защите и регулярно проводить аудит безопасности приложений.

Подписывайся / Чат
👍5
Немного слов о State of JS

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

+12% retention
+5% usage
+5% positivity

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

Что касается React, то он продолжает уверенно удерживать лидирующие позиции. Но отмечается потребность в более простых подходах, поскольку API стал более неоднозначным, особенно с его RSC.

А вот самым используемым и с высоким уровнем удовлетворенности стал Vite и Vitest соответственно. И неудивительно с его количеством интеграций в различные инструменты.

Посмотреть подробности, поиграть с фильтрами здесь.

Подписывайся / Чат

#js
🔥5
После принятого разработчиками Angular решения в 19 версии сделать компоненты standalone по умолчанию, продолжаем ждать, когда же ChangeDetection: OnPush стратегия будет также по умолчанию включена.🤔

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

Особенно актуально с ребрендингом:

ChangeDetection >> Synchronization.

Подписывайся / Чат

#angular
👍6👏1
Всех с наступающим Новым годом!🎄🎉🎉🎉🎉🎉
Вернемся к новостям уже в следующем!

Спасибо, что подписаны! Хотим пожелать нам всем профессионально развиваться и не забывать отдыхать!
🎄11👌1
А мы возвращаемся и продолжаем стримить новости фронтенда! 🎉🎉🎉

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

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

export class RiskyService {
private injector: Injector;

// This creates a hidden dependency outside of construction
performAction() {
runInInjectionContext(this.injector, () => {
// Service locator pattern: Looking up service on demand
const analyticsService = inject(AnalyticsService);
analyticsService.track(data);
});
}
}


Советую ознакомиться, потому что важно знать, к каким потенциальным проблемам это может привести и разумно применять существующие подходы. База, как говорится:) Особенно, когда Angular стал предоставлять все больше случаев возможностей реализации для одного и того же.

#angular
👍4
Input signals - production-ready

В 19 версии были добавлены схематики, позволяющие произвести миграцию Input на декораторах на сигнальные. О чем я писал в заметке.

ng generate @angular/core:signal-input-migration
ng generate @angular/core:signal-queries-migration


Сейчас команда Angular выпустила заметку в своем блоге, где говорит о переходе сигнальных Input в статус production-ready. Основная причина перехода - типобезопасность, которая позволит разработчикам, например, не писать лишний раз non-null assertions. И отказаться от ngOnChanges().

Заметка простая, но интересно, что команда намекает о необходимости перехода на новое API. Подчеркивается, что комбинация с computed() улучшит читаемость и тд.

Сейчас как раз планирую взять задачу по тех долгу, в которой, помимо декомпозиции и прочего, реализовать функционал на новом API.👍🏻

#angular
👍2
Несовершенства TS

На неделе заметил интересный issue в репозитории Typescript. В нем обсуждается предложение добавить новый модификатор identity для функций.

Основная идея в том, чтобы позволить разработчикам указывать, что функция возвращает неизмененное и равное по ссылке значение, которое должно быть сужено до конкретного типа при каждом вызове (если бы это было простое значение, а не результат функции).

Если добавить чуть больше контекста для понимания, то автор обеспокоен тем, что сигналы нужно проверять на наличие undefined, потому что TS не может нормально сузить тип, который возвращается в value(). А использование этого ключевого слова позволило бы избежать необходимости писать лишние проверки.

declare const value: () => string | undefined;

if (value() !== undefined) {
console.log(value().toUpperCase()); // Ошибка компиляции
}


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

#typescript

Подписывайся / Чат
👍1