Frontend
Angular #
Angular Core #
DI + providers
Junior #
Что такое InjectionToken и когда он нужен?
|
TypeScript interface отсутствует в runtime и не может быть DI token.
Описание токена должно быть уникальным и понятным. Для tree-shakable default можно передать |
Что такое inject() и injection context?
|
Нельзя вызывать |
Как разделять API service, state service и facade?
Для маленькой feature три класса могут быть лишними. Разделение вводят, когда обязанности действительно различаются. Компонент отвечает за rendering и UI events, а бизнес-правила не должны зависеть от DOM. |
Как подменять dependencies в Angular-тестах?
Предпочтительны небольшие fake/stub реализации с типом |
Объясните как работает Dependency Injection на примере SOLID
|
Как мы помним Dependency Injection в Angular это механизм, при котором класс не создает зависимости сам, а получает их снаружи. То есть вместо:
мы пишем:
Angular сам найдет UserApiService, создаст экземпляр и передаст его в компонент. Зачем это нужно: Представь компонент:
Компоненту не хочется знать:
Компоненту нужно только сказать: “Дай мне сервис, который умеет загружать профиль”. Это и есть идея Dependency Injection. Без Dependency Injection Плохой вариант:
Проблемы:
С Dependency Injection Хороший вариант:
Теперь ProfileComponent не создает ProfileService. Он только просит Angular: “Найди мне зависимость типа ProfileService”. Angular смотрит в injector и возвращает нужный экземпляр. Как это связано с SOLID 1. S — Single Responsibility Principle Класс должен иметь одну основную ответственность. Без DI компонент часто делает слишком много:
Компонент отвечает и за UI, и за работу с API. Лучше разделить:
Теперь:
DI помогает не смешивать ответственности. 2. O — Open/Closed Principle Код должен быть открыт для расширения, но закрыт для изменения. Допустим, есть аналитика:
Компонент использует ее:
Если завтра нужно заменить ConsoleAnalyticsService на FirebaseAnalyticsService, не хочется переписывать все компоненты. В Angular можно сделать абстракцию через InjectionToken:
Реализация:
Provider:
Использование:
Теперь компонент не зависит от конкретного класса. Можно заменить реализацию:
Компонент не меняется. 3. L — Liskov Substitution Principle Любую реализацию интерфейса можно заменить другой, если она соблюдает тот же контракт. Например, у нас есть контракт:
Одна реализация хранит токен в localStorage:
Другая — в памяти:
DI позволяет подставить любую реализацию:
А потребитель не знает, какая реализация внутри:
Если заменить LocalStorageAuthStorage на MemoryAuthStorage, AuthService должен продолжить работать. 4. I — Interface Segregation Principle Не заставляй класс зависеть от методов, которые ему не нужны. Плохо:
Компоненту профиля нужен только loadUser, но он зависит от огромного интерфейса. Лучше разделить:
Токен:
Компонент:
Компонент зависит только от того, что ему реально нужно. 5. D — Dependency Inversion Principle Это главный принцип, связанный с DI. Высокоуровневый код не должен зависеть от низкоуровневых деталей. Оба должны зависеть от абстракций. Плохо:
AuthService зависит от конкретной детали: LocalStorageAuthStorage. Лучше:
Теперь AuthService зависит не от конкретной реализации, а от абстракции. Главная мысль DI в Angular — это не просто “удобно получить сервис”. Это способ сделать код:
Самая важная связь с SOLID — это Dependency Inversion: Компонент или сервис должен зависеть не от конкретной реализации, а от контракта/абстракции. |
Middle #
Как избежать circular dependency в Angular?
|
Сначала проверяют архитектуру: циклическая DI или import-зависимость часто означает смешение ответственности. Варианты исправления:
Import cycles проверяют инструментами dependency graph и правилами ESLint/Nx. |
Middle+ or Senior #
Что такое DI в Angular?
|
Angular DI — это система, через которую Angular создает и передает зависимости компонентам, директивам, сервисам и
другим сущностям. Сервисы можно регистрировать через
Legacy constructor injection тоже поддерживается, но в новом standalone-коде часто используют |
Что такое provider и чем отличаются useClass, useValue, useFactory и useExisting?
|
Provider связывает DI token со способом получения значения:
|
Что делает providedIn: 'root'?
|
Это подход по умолчанию для stateless-сервисов, API-клиентов и общего состояния приложения. |
Чем отличается providedIn: 'root' от providers в компоненте?
|
Локальный |
Что будет, если один сервис есть и в root, и в providers компонента?
|
Будут существовать разные экземпляры сервиса. Angular начинает поиск с ближайшего инжектора, поэтому компонент и его потомки получат локальный экземпляр, а остальные части приложения продолжат использовать root-экземпляр. Это называется shadowing провайдера.
Такое поведение полезно для изоляции состояния, но может стать причиной ошибок, если разработчик ожидал настоящий singleton. |
Как диагностировать provider scope и случайные разные instances?
|
Если сервис неожиданно хранит разное состояние в разных частях приложения, сначала проверяют, где он зарегистрирован:
Angular всегда берет ближайший подходящий provider в иерархии injectors. Поэтому component provider может скрыть root provider, а route provider может создать отдельный instance для lazy feature. Практическая диагностика:
Если сервис должен быть singleton, обычно достаточно |
Основные концепции #
Junior #
Что такое Angular?
|
Angular — TypeScript-платформа для создания web-приложений. Она включает compiler, declarative templates, components, signals, DI, Router, forms, HttpClient, SSR/SSG/hydration, service worker, CLI и testing APIs. Современная модель Angular 19–22:
Плюсы: единая экосистема, строгая типизация шаблонов, предсказуемая архитектура, хороший tooling и масштабируемость. Минусы: большой API surface, необходимость понимать DI, reactivity, Router, rendering и RxJS; неправильные границы состояния или feature могут сделать приложение сложным независимо от выбранного state manager. |
Что такое TypeScript и зачем он нужен Angular?
|
TypeScript — надмножество JavaScript со статической типизацией. Angular использует TypeScript для описания компонентов, DI-контрактов, маршрутов, forms, HTTP DTO и strict template checking. Типы помогают находить ошибки до runtime:
TypeScript не заменяет runtime-валидацию данных с backend, но делает код приложения явнее и безопаснее для рефакторинга.
В Angular особенно важны |
Что такое Angular CLI?
|
Angular CLI — официальный инструмент для создания, сборки, разработки и обновления Angular-проектов. Через CLI обычно запускают dev server, production build, schematics, migrations и тесты. Примеры:
CLI важен не только как генератор файлов. Он скрывает конфигурацию builder-а, TypeScript compilation, dev server, production optimizations, assets, styles и migrations под единым API. |
Что такое platform, declarable и bootstrapped component?
|
Platform — слой Angular, который связывает приложение с окружением выполнения: browser, server, tests или custom
renderer. В browser-приложении Declarable — исторический термин из NgModule-модели: component, directive или pipe, которые добавляли в Bootstrapped component — корневой компонент, с которого начинается component tree. В standalone-приложении это аргумент
|
Что такое MVVM и в чем разница перед MVC?
|
MVVM - шаблон проектирования архитектуры приложения. Состоит из 3 ключевых блоков: Model, View, ViewModel. Отличие от MVС заключаются в:
Привязка данных между View и ViewModel может быть односторонней или двусторонней (one-way, two-way data-binding). |
Middle #
В чем разница между AngularJS и Angular?
|
AngularJS является фреймворком, который может помочь вам в разработке Single Page Application. Он появился в 2009 году и с годами выяснилось, что имел много проблем. Angular (Angular 2+) же в свою очередь направлен на тоже самое, но дает больше преимуществ по сравнению с AngularJS 1.x, включая лучшую производительность, ленивую загрузку, более простой API, более легкую отладку. Что появилось в Angular:
Основные преимущества Angular:
|
Какой должна быть структура каталогов компонентов любого Angular приложения и почему?
|
Универсальной структуры нет: она зависит от размера продукта и команды. Для приложения обычно лучше группировка по
feature/domain, а не один глобальный каталог
Главные критерии: связанный код находится рядом, публичный API узкий, зависимости направлены от feature к общим слоям, а не между случайными feature. |
Middle+ or Senior #
Что такое component, directive, template и metadata?
|
Компонент — директива с собственным шаблоном. Он описывает часть UI, принимает данные через inputs, сообщает события через outputs и может иметь локальные providers. Директива добавляет поведение существующему элементу или шаблону. Атрибутная директива меняет поведение элемента, а
структурная директива управляет embedded view. Для обычных условий и циклов в новом Angular чаще используют Template — HTML-подобный шаблон Angular с bindings, control flow, pipes и template variables. Metadata — конфигурация decorator-а, например
|
Какая базовая архитектура Angular-приложения?
|
Современное Angular-приложение обычно состоит из:
Feature-код лучше группировать по доменам, а не только по техническим типам. NgModules остаются поддерживаемой legacy/enterprise-compatible моделью: они встречаются в старых проектах, библиотеках и постепенных миграциях, но не являются главным способом проектировать новое приложение. |
Templates #
Junior #
Для чего нужен track в @for?
|
Лучший ключ — стабильный уникальный id. |
Что такое интерполяция в Angular?
|
Разметка интерполяции с внедренными выражениями используется в Angular для присвоения данных текстовым нодам и значения аттрибутов. Например:
|
Middle #
Что такое standalone component и чем он отличается от NgModule-подхода?
|
Standalone-компонент напрямую импортирует зависимости шаблона через
С Angular 19 компоненты, директивы и pipes standalone по умолчанию. Standalone упрощает lazy loading, локальные
зависимости и tree shaking. |
Как работают @if, @for, @switch и @let?
Built-in control flow не требует |
Какие способы использования шаблонов в Angular вы знаете?
|
Шаблон можно задать:
В шаблонах используются интерполяция, property/event binding, control flow Для обычного компонента предпочтителен внешний |
В чем разница между структурной и атрибутной директивой, назовите встроенные директивы?
|
Структурные директивы управляют структурой представления: создают, удаляют или повторяют embedded views.
Классические примеры — В Angular 19–22 для обычных условий и циклов используют встроенный control flow:
Атрибутные директивы изменяют поведение или свойства существующего элемента. Примеры: Для классов и стилей предпочтительны прямые bindings:
|
Чем hidden отличается от @if или *ngIf?
|
Используйте |
Для чего нужны директивы ng-template, ng-container, ng-content?
|
В современном Angular:
Ниже приведен legacy-синтаксис 1. ng-template
Template можно представить себе как фрагмент контента, сохраненный для последующего использования в документе. Хотя
парсер и обрабатывает содержимое элемента
Пример:
2. ng-container
На самом деле структурные директивы (*ngIf, *ngFor, …) являются синтаксическим сахаром для наших шаблонов. В реальности, данные шаблоны трансформируются в такие конструкции:
Но что делать, если я хочу применить несколько структурных директив? (спойлер: к сожалению, так нельзя сделать)
Но можно сделать так:
Однако, чтобы избежать необходимости создавать дополнительный div, мы можем вместо этого использовать директиву ng-container:
Как мы видим, директива ng-container предоставляет нам элемент, в котором мы можем использовать структурную директиву, без необходимости создавать дополнительный элемент. Еще пара примечательных примеров, если все же вы хотите использовать ng-template вместо ng-container, по определенным правилам вы не сможете использовать полную конструкцию структурных директив. Вы можете писать либо так:
Либо так:
На выходе, при рендеринге будет одно и тоже:
3. ng-content
Здесь на самом деле, немного сложнее уже чем с ng-template, ng-container. Так как ng-content решает задачу проецирования контента в ваши веб-компоненты. Веб-компоненты состоят из нескольких отдельных технологий. Вы можете думать о Веб-компонентах как о переиспользуемых виджетах пользовательского интерфейса, которые создаются с помощью открытых веб-технологий. Они являются частью браузера и поэтому не нуждаются во внешних библиотеках, таких как jQuery или Dojo. Существующий Веб-компонент может быть использован без написания кода, просто путем импорта выражения на HTML-страницу. Веб-компоненты используют новые или разрабатываемые стандартные возможности браузера. Давайте представим ситуацию от обратного, нам нужно параметризовать наш компонент. Мы хотим сделать так, чтобы на вход в компонент мы могли передать какие-либо статичные данные. Это можно сделать несколькими способами. comment.component.ts:
app.component.html
Но можно поступить и другим путем. comment.component.ts:
app.component.html
Конечно, эти примеры плохо демонстрируют подводные камни, свои плюсы и минусы. Но второй способ демонстрирует подход при работе, когда мы оперируем независимыми абстракциями и можем проецировать контент внутрь наших компонентов (подход веб-компонентов). |
Middle+ or Senior #
Что такое template expression, template statement и какие операторы доступны?
|
Template expression вычисляет значение для interpolation, property binding, class/style binding или pipe:
Template statement выполняется в response на событие:
В expression доступны обычные безопасные операции чтения: property access, method call без side effects, arithmetic,
comparison, logical operators, Pipe имеет более низкий приоритет, чем ternary, поэтому неоднозначные выражения лучше группировать скобками:
|
Templates и content projection #
Junior #
Что такое template reference variable?
|
Template reference variable объявляется через
Для работы из класса компонента используют queries, например |
Middle #
Почему вызов функции в template может быть проблемой?
|
Template expression может выполняться много раз при проверках. Если функция тяжелая, создает новые объекты или имеет побочные эффекты, UI станет медленнее и поведение будет непредсказуемым. Лучше вынести вычисление в |
Что будет, если несколько раз использовать async pipe на одном cold Observable?
|
Каждый Решения: вынести значение через |
Чем ng-content, ng-container и ng-template отличаются друг от друга?
|
Коротко: |
Как использовать input/output aliasing?
|
Alias меняет публичное имя binding-а в шаблоне, но не имя свойства в классе. Это полезно для совместимости, более понятного template API или директив, где input совпадает с selector.
Alias не стоит использовать без причины: разные имена в class API и template API усложняют поиск и рефакторинг. |
Как выбрать элемент внутри template и как работают ViewChild / ContentChild?
|
Для доступа к элементу внутри шаблона можно использовать template reference variable:
Из класса компонента используют view queries для собственного шаблона и content queries для projected content:
В новых компонентах signal queries обычно удобнее decorator queries: они типизированы как signals и обновляются
реактивно. В legacy |
Middle+ or Senior #
Чем property binding отличается от interpolation?
|
Interpolation
Для boolean, object, array и component inputs обычно используют property binding. |
Чем property binding отличается от attribute binding?
|
Property binding меняет runtime-свойство элемента или input директивы. Attribute binding
Если значение attribute равно |
Компоненты, директивы, сервисы и pipes #
Junior #
Что такое директива и как создать собственную?
|
Директивы бывают трех видов: компонент, структурные и атрибутные (см. выше). Современная атрибутная директива использует
В новом коде объект Пользовательская структурная директива работает с
Для обычных условий собственная структурная директива не нужна: используйте Через CLI директиву создают командой:
|
Что такое директива, компонент, модуль, сервис, пайп в Angular и для чего они нужны?
|
Что такое динамические компоненты и как их можно использовать в Angular?
|
Динамические компоненты создаются во время выполнения. Типичные случаи: dialogs, overlays, notifications и конфигурируемые widgets. В Angular 19–22 есть три основных варианта:
Для глобальных overlays обычно используют Angular CDK Overlay или API UI-kit. |
Middle #
Как применить анимацию к компонентам?
|
В Angular 20.2+ для нового кода рекомендуются CSS-анимации и compiler APIs
Для сложной timeline-анимации можно передать функцию и интегрировать GSAP или другую библиотеку. Нужно учитывать
Legacy DSL из |
Middle+ or Senior #
Расскажите об основных параметрах @NgModule, @Component, @Directive, @Injectable, @Pipe
|
В Angular 19–22 основной подход — standalone. Компоненты, директивы и pipes standalone по умолчанию; Основные параметры:
Inputs, outputs и queries в новом коде объявляют в классе:
|
Angular low-level API #
Junior #
Для чего нужен Renderer2?
|
Его используют редко: когда declarative bindings, host metadata или CDK API не подходят. Прямые DOM-операции через
|
Что такое TemplateRef?
|
Его можно передать в компонент, получить через query или использовать в структурной директиве, а затем создать embedded
view через |
Что такое ViewContainerRef?
|
Типичные случаи: структурные директивы, dynamic dialogs, plugin-like UI и lazy widgets. Владелец контейнера также управляет порядком, очисткой и уничтожением созданных views. |
Middle #
Что такое HostListener и почему это legacy API?
|
Host listener полезен для поведения директивы, которое принадлежит host-элементу, например hover, focus или keyboard interaction. |
Когда можно использовать ElementRef?
|
Нельзя без необходимости менять DOM через |
Чем ViewChild отличается от ContentChild?
|
View queries доступны после инициализации view, content queries - после инициализации projected content. В новом коде
часто используют signal queries: |
Middle+ or Senior #
Что такое HostBinding и почему это legacy API?
|
|
Зачем использовать queueMicrotask внутри Angular host listener?
|
Это не универсальное решение и не способ чинить плохую архитектуру. Если порядок действий важен для бизнес-логики, лучше сделать явную orchestration-логику через сервис, store, output/input или отдельный event coordinator. Пример неявной зависимости от порядка host listeners:
Если
Разница с
Когда может быть полезно:
Проблемы и риски:
Тестировать можно обычным async-тестом:
Или через Angular
|
Зачем нужен Renderer2 и чем он помогает в отличие от ElementRef.nativeElement или declarative binding в host?
|
В большинстве host-взаимодействий лучше начинать с declarative bindings в
Отличия:
Прямой |
Для чего нужен NgZone?
|
В zoneless Angular роль |
NgModules legacy #
Junior #
Как standalone components заменили часть NgModule-сценариев?
|
Standalone component сам объявляет template dependencies через
Так меньше скрытых module boundaries, проще lazy loading и понятнее зависимости шаблона. |
Middle #
Зачем раньше был нужен NgModule?
|
|
Чем forRoot отличается от forChild?
|
Это legacy pattern для NgModule-based libraries. В standalone Angular его часто заменяют |
Для чего использовали SharedModule?
|
В standalone-подходе чаще импортируют конкретные зависимости прямо в компонент или route. Это делает связи явнее и уменьшает случайный общий API. |
Почему SharedModule не должен провайдить singleton services для lazy modules?
|
Lazy module может получить собственный child injector. Если Singleton services лучше объявлять через |
Middle+ or Senior #
Что означают declarations, imports, exports и providers в NgModule?
|
В standalone-компонентах большую часть |
Pipes #
Junior #
Что такое pure pipe?
|
Pure pipe пересчитывается только когда меняется ссылка на input или primitive value. Это режим по умолчанию и лучший выбор для чистых форматирований. Pipe должен быть без side effects: одинаковый input дает одинаковый output. |
Что такое impure pipe?
|
Impure pipe ( Используйте его только для редких случаев, где нельзя выразить обновление через signals, Observable, immutable update или pure pipe. |
Middle #
Что делает async pipe?
|
Он удобен для template-facing streams, но несколько |
Как создать custom pipe?
|
Pipe объявляют через
|
Когда pipe лучше computed() или helper function?
|
Pipe хорош для отображения значения в шаблоне: форматирование даты, валюты, имени, статуса, короткого текста. Pure pipe кеширует результат относительно входных значений и не смешивает rendering с бизнес-логикой.
Helper function допустима для маленькой чистой операции, но вызов из template может выполняться часто. Если функция
создает новые объекты, фильтрует большие массивы или делает тяжелую работу, лучше Custom pipe не нужен, если преобразование используется один раз и проще читается как подготовленное поле в компоненте. Impure pipe почти всегда сигнал, что состояние или поток данных спроектированы неудачно. |
Middle+ or Senior #
Как pipes влияют на performance?
|
Pure pipes помогают не выполнять одно и то же форматирование на каждом render, если input references стабильны. Impure pipes и тяжелые преобразования в больших списках могут стать hot path. Для дорогих вычислений используйте memoization, |
Lifecycle и rendering #
Middle+ or Senior #
Объясните механизм загрузки (bootstrap) Angular-приложения в браузере?
|
Современное standalone-приложение запускается через
Angular создает root NgModule-bootstrap через |
Что происходит после загрузки Angular bundle?
|
Браузер загружает, парсит и выполняет JavaScript bundle. Entry point вызывает Дальше запускается initial rendering: Angular строит component tree, выполняет bindings, создает DOM nodes и подключает event listeners. Если подключен Router, стартовая навигация выбирает route, может загрузить lazy bundle, выполнить guards/resolvers и отрендерить routed component. При SSR/SSG пользователь может увидеть HTML до client bundle. После загрузки bundle Angular выполняет hydration: связывает существующий DOM с component tree, providers и обработчиками событий. Large bundle, тяжелые initializers, blocking guards или hydration mismatch задерживают интерактивность. |
Как происходит взаимодействие компонентов в Angular (опишите components view)?
|
Основные способы взаимодействия:
Для двухсторонней привязки:
Для общего синхронного состояния сервис может инкапсулировать writable signal и наружу отдавать readonly signal. RxJS используют для асинхронных потоков и сложной координации.
|
Каков жизненный цикл у компонентов?
|
Angular 19–22 поддерживает классические lifecycle hooks и render callbacks. Классические hooks:
Современные render callbacks:
Для cleanup удобно использовать
При signal inputs многие реакции выражаются через |
В каком порядке вызываются lifecycle hooks?
|
При первом render порядок обычно такой: Render callbacks вроде |
Для чего нужен ngOnChanges?
|
Он полезен, когда реакция зависит от сравнения старого и нового значения. В signal input коде часто хватает |
Когда использовать ngAfterViewInit?
|
Менять уже проверенное состояние прямо в этом hook опасно: можно получить ошибку проверки. Часто лучше использовать
|
Когда использовать ngAfterContentInit?
|
Если нужен элемент из собственного шаблона компонента, это view lifecycle, а не content lifecycle. |
Чем view lifecycle отличается от content lifecycle?
|
Content lifecycle относится к projected content, который родитель передал внутрь компонента. View lifecycle относится к собственному шаблону компонента и его view children. Поэтому |
Как lifecycle связан с subscriptions, effects и cleanup?
|
Все, что живет дольше одного synchronous render, должно иметь понятный lifetime: подписки, DOM listeners, timers, WebSocket, observer APIs и effects. В Angular для cleanup используют:
|
Что такое Shadow DOM и как с ним работать в Angular?
|
Shadow DOM — браузерный механизм инкапсуляции DOM-поддерева и стилей web component. Внешние стили по умолчанию не проникают внутрь shadow tree, а внутренние не влияют на остальную страницу. Angular поддерживает режимы
При |
Что такое Data Binding и какие проблемы связанные с ним вы знаете?
|
Data Binding связывает template expression со свойством, атрибутом, классом, стилем или событием.
Для component inputs и outputs используется тот же синтаксис:
Двусторонняя привязка раскрывается в input + output
Типичные проблемы: тяжелые вычисления в шаблоне, вызовы методов с side effects, мутация объектов с OnPush, неявный сложный two-way data flow и неправильное различение property binding и attribute binding. |
Как вы используете одностороннюю и двухстороннюю привязку данных?
|
Односторонняя привязка имеет явное направление:
Двусторонняя привязка объединяет property и event binding:
Для компонентов предпочтителен model input:
|
В чем преимущества и недостатки Regular DOM (Angular) перед Virtual DOM (React)?
|
Формулировка упрощает реальность: и Angular, и React в итоге обновляют настоящий DOM, но используют разные модели определения изменений. Angular компилирует шаблон в точные инструкции создания и обновления узлов. Ему не обязательно каждый раз строить новое виртуальное дерево и сравнивать его целиком. React обычно создает новое представление Virtual DOM и выполняет reconciliation. Преимущества подхода Angular:
Возможные недостатки:
Нельзя утверждать, что один подход всегда быстрее. Нужно измерять конкретный сценарий: большие списки, частые события, startup, memory и стоимость обновления. |
Что такое ngZone?
|
Важно для Angular 19–22:
В zoneless-приложении Angular получает точные уведомления от signals, template/host listeners,
|
Как обновлять представление, если ваша модель данных обновляется вне 'зоны'?
|
В современном Angular предпочтительно записать новое значение в signal. Это работает и в zoneless-приложении:
Если сторонний callback изменяет обычное поле, можно вызвать
Ниже приведены legacy-варианты ручного запуска change detection.
Метод
|
Что такое output(), EventEmitter и как подписываться на события?
|
Для нового компонента custom event объявляют через
Angular автоматически очищает подписки при уничтожении компонента. Outputs не всплывают по DOM.
|
Angular component styling #
Junior #
Для чего нужен :host в стилях компонента?
|
|
Для чего нужен :host-context?
|
Не стоит строить на нем сложную зависимость от DOM-иерархии: темы обычно надежнее передавать через CSS custom properties или явные classes. |
Что такое ViewEncapsulation?
|
Режим выбирают по требованиям дизайн-системы, SSR, theming и интеграции со сторонними стилями. |
Как стилизовать projected content?
|
Projected content принадлежит родительскому view, поэтому стили дочернего компонента с encapsulation не всегда применяются к внутренним элементам projection. Надежные варианты: стилизовать wrapper вокруг |
Middle #
Почему ::ng-deep считают legacy escape hatch?
|
Предпочтительнее public theming API, CSS variables, component inputs/classes, global styles для настоящих global rules или настройка дизайн-системы. |
Dependency Injection #
Junior #
Что такое Singleton Service и с какой целью его используют в Angular?
|
Это сервисы, объявленные в приложении и имеющие один экземпляр на все приложение. Его можно объявить двумя способами:
Provider в компоненте или route создает scoped instance, а не глобальный singleton. При lazy routes могут существовать
дочерние
NgModule |
Middle+ or Senior #
Чем DI-паттерн отличается от Angular DI?
|
Dependency Injection как паттерн означает, что класс не создает зависимости сам, а получает их снаружи. Это уменьшает связанность и упрощает тестирование. Angular DI — конкретная реализация этого паттерна: Angular хранит providers в иерархии injectors, находит dependency по token и управляет lifetime экземпляров. Базовый пример Angular DI см. в вопросе «Что такое DI в Angular?». |
Как можно определить свой обработчик ErrorHandler, Logging, Cache в Angular?
|
Глобальные необработанные ошибки можно направить в собственный
HTTP-ошибки, logging и HTTP-cache удобно централизовать функциональными interceptors через
Важно разделять ответственность:
Не следует автоматически повторять все запросы или кешировать мутации. |
Angular Change Detection #
Middle+ or Senior #
Что такое Change Detection, как работает Change Detection Mechanism?
|
Change Detection — синхронизация состояния приложения с DOM. Angular выполняет скомпилированные инструкции шаблона и обновляет bindings, значения которых изменились. Angular должен получить уведомление, что view может быть dirty. Основные источники:
В zone-based приложении ZoneJS также планирует синхронизацию после async-задач. В zoneless Angular опирается на точные уведомления; начиная с Angular 21 zoneless используется по умолчанию. Во время одной проверки Angular обходит дерево views сверху вниз. Не следует менять уже проверенное состояние во время рендера. |
Сколько Change Detector(ов) может быть во всем приложении?
|
У каждого component view есть собственное представление change detection, связанное в дерево views. Ivy как отдельная
тема является historical topic: сегодня это обычный runtime Angular, а его внутренние структуры Через |
Основное отличие constructor от ngOnInit?
|
Конструктор — механизм JavaScript/TypeScript. Angular создает экземпляр класса и предоставляет injection context,
поэтому зависимости можно получать через
Signal inputs можно читать в Для DOM-зависимой логики используют |
Чем markForCheck() отличается от detectChanges(), detach() и reattach()?
Для OnPush обычно нужен |
Что такое coalescing Change Detection и как найти лишние проверки?
|
Coalescing объединяет несколько событий или вызовов Диагностика:
Сначала измеряют конкретный сценарий, затем оптимизируют component boundaries, список, вычисления или scheduling. |
Что такое zoneless Angular?
|
Zoneless Angular — режим, в котором Angular не полагается на ZoneJS для глобального перехвата async APIs. Вместо этого view помечается dirty точными уведомлениями:
В Angular 20 zoneless включали через Практический смысл: меньше магии вокруг async tasks и больше явных реактивных источников. Код, который меняет обычное
поле из стороннего callback и рассчитывает на ZoneJS, нужно перевести на signal, |
Какие существуют стратегии обнаружения изменений?
|
Есть две стратегии:
Нельзя мутировать объект input на месте и ожидать новую ссылку. Предпочтительны immutable updates и signals. |
Angular Signals #
Middle+ or Senior #
Что такое Signals и когда их использовать?
|
Signal — реактивный контейнер для значения. Angular отслеживает чтение signal и обновляет зависящие от него вычисления и представления при изменении.
Inputs и queries также являются signals:
Signals подходят для локального синхронного состояния, derived state и template-facing значений. RxJS удобнее для отмены, событий во времени, WebSocket, polling и сложной оркестрации. Эти инструменты дополняют друг друга. |
В чем разница между input(), output() и model()?
|
В чем разница между computed(), effect() и linkedSignal()?
|
Кратко: |
Когда использовать resource(), httpResource() и RxJS?
|
Они удобны, когда компоненту нужен один текущий async-result, зависящий от signals:
RxJS предпочтительнее для сложных событий во времени: WebSocket, polling, debounce, объединение потоков, backpressure-подобные сценарии и явная композиция операторов.
|
RxJS #
Middle+ or Senior #
Чем cold Observable отличается от hot Observable?
|
Cold Observable запускает producer отдельно для каждой подписки. Hot Observable имеет общий producer для подписчиков. Примеры: DOM events, WebSocket,
|
Как выбрать switchMap, mergeMap, concatMap или exhaustMap?
Для mutation-запросов |
Как построить autocomplete с отменой запроса?
|
Где ставить catchError: внутри или снаружи switchMap?
|
Внутри — если ошибка относится к одной inner operation и внешний поток должен продолжить работать:
Снаружи — если любая ошибка должна завершить или полностью заменить весь pipeline. Для UI events чаще нужен внутренний
|
Какие проблемы возможны у shareReplay()?
|
Риски:
Нужно явно определить ключ, срок жизни, refresh и очистку кеша. |
Когда нужна ручная отписка и что делает takeUntilDestroyed()?
|
От finite streams ( От бесконечных streams в imperative subscription нужно отписаться:
|
Чем combineLatest, withLatestFrom и forkJoin отличаются?
|
Чем debounceTime, throttleTime и auditTime отличаются?
Для resize/scroll часто подходит |
Для чего нужен RxJS и какую проблему он решает?
|
RxJS предоставляет модель потоков для асинхронных значений и событий. Он помогает декларативно описывать:
Сила RxJS не в замене Promise, а в композиции последовательностей из нуля, одного или многих значений. Для простого локального синхронного состояния в Angular чаще достаточно signals; для сложной асинхронной координации RxJS остается подходящим инструментом. |
Что такое Observable?
|
Observable - ленивый поток значений. Он начинает работу при подписке и может передать ноль, одно или несколько значений, ошибку и сигнал завершения. |
Что такое Observer, subscription и обработка ошибок в Observable?
|
Observer — объект или набор callbacks, который получает уведомления Observable:
Subscription — результат
Если не передать |
Для чего нужны map, tap и filter в RxJS?
|
|
В чем разница между Observable и Promise?
|
Promise возвращает один будущий результат и начинает выполнение сразу после создания. Observable ленивый, может передать несколько значений и предоставляет операторы для композиции, повторов и отмены через отписку. Для одного простого результата подходит Promise. Для пользовательских событий, WebSocket, polling и сложной координации потоков обычно используют RxJS. |
Чем Observable отличается от Subject?
|
Обычный cold Observable обычно запускает producer отдельно для каждой подписки. |
В чем разница между Subject, BehaviorSubject, ReplaySubject, AsyncSubject?
Для состояния Angular-компонента чаще используют signals. Subject остается полезен на RxJS-границах и для потоков событий. |
Чем отличаются switchMap, mergeMap и concatMap?
|
Как бы вы кешировали наблюдаемые данные из потоков (stream)?
|
Способ зависит от срока жизни, ключа и политики инвалидирования кеша. Для совместного использования результата
HTTP-запроса часто применяют
Нужно учитывать:
На уровне HTTP также применяют browser cache, |
RxJS practical cases #
Middle+ or Senior #
Как избежать race condition в RxJS-загрузке данных?
|
Race condition возникает, когда более старый async result приходит позже нового и перезаписывает актуальное состояние.
Для route params, поиска и фильтров обычно используют Для write operations чаще выбирают |
Как выполнить API-запросы строго по порядку?
|
Используйте
Для независимых запросов подойдет |
Как переиспользовать результат запроса между routes?
|
Вынесите загрузку и кеш в сервис, который живет дольше конкретного route component: root service, feature provider или route-level provider на общем parent route. Компоненты читают один и тот же stream/signal из сервиса. Ключ кеша должен учитывать params, пользователя и правила инвалидирования. |
Как объединить route params и UI events?
|
Route params и UI events превращают в streams и объединяют через
Важно задать initial value для UI stream, иначе |
Чем scan отличается от reduce в RxJS?
|
|
Angular Forms #
Middle+ or Senior #
Чем Reactive Forms отличаются от template-driven forms?
|
Reactive Forms создают model в TypeScript, дают typed controls, synchronous state и удобное тестирование. Они подходят сложным формам и динамической структуре. Template-driven forms создают model преимущественно через directives в шаблоне. Они удобны для небольших простых форм, но хуже масштабируются. В Angular 21–22 для нового signal-first кода доступны Signal Forms. Выбор зависит от версии и архитектуры существующего проекта. |
Чем setValue отличается от patchValue и что делают emitEvent/onlySelf?
Эти флаги используют осторожно: подавленное событие может оставить derived state несинхронизированным. |
Что такое ControlValueAccessor и когда писать свой CVA?
|
Методы:
Контрол регистрируется через multi-provider |
Как правильно реализовать disabled, touched и dirty в кастомном контроле?
Для составного контрола нужно определить, когда группа считается touched и какое значение считается атомарным. |
Как строить nested и reusable forms без лишних подписок?
|
Родитель может передать дочернему компоненту typed Derived validation и UI state лучше получать из control state или signals. Если нужна подписка на |
Что такое FormGroup и FormControl и для чего они используются?
|
В strictly typed Reactive Forms:
|
Что такое реактивные формы в Angular?
|
Reactive Forms — стабильный model-driven API на основе В Angular 21+ также доступны Signal Forms из
Signal Forms лучше подходят новым signal-first приложениям на Angular 21–22. Для Angular 19–20 и существующих production-приложений strictly typed Reactive Forms остаются надежным выбором. |
Как применять валидацию для простых и сложных форм?
|
В Reactive Forms валидаторы передают control при создании или через
Signal Forms используют schema validators: Backend всегда повторно валидирует данные: frontend-валидация нужна для UX, а не является границей безопасности. |
Что такое NgForm?
|
Она удобна для простых форм, но для сложной typed logic, динамических controls и тестирования чаще выбирают Reactive Forms или Signal Forms в новых версиях Angular. |
Для чего нужен FormBuilder?
|
|
Что означают dirty, touched и pristine в Angular Forms?
|
Обычно validation errors показывают после |
Как показывать validation errors в template?
|
Показывайте ошибку, когда control invalid и пользователь уже взаимодействовал с полем или отправил форму. Условие лучше держать простым и не вызывать тяжелые функции в template.
Текст ошибки должен быть рядом с полем и связан с ним доступным способом, например через |
Как работают async validators?
|
Async validator возвращает Promise или Observable с Типичный пример - проверка уникальности username. Внутри нужно отменять/ограничивать лишние запросы и не считать frontend-валидацию границей безопасности. |
Angular HTTP #
Middle #
Как делать retry и отмену HTTP-запросов?
|
Retry применяют только для временных и безопасных ошибок:
Нельзя бездумно повторять mutations и ошибки |
Как реализовать refresh token без бесконечного цикла?
|
Auth interceptor:
Нужно различать истекший token и отсутствие permissions. Счетчик/контекст запроса предотвращает повторный refresh loop. |
Как мокать HTTP в Angular-тестах?
Тест проверяет method, URL, body, headers, mapping и error handling. Для development mocks используют отдельный mock server, service worker mocking или proxy, не production interceptor. |
Как Angular-приложение взаимодействует с backend API?
|
Взаимодействие с API В экосистеме ангуляр существует пакет для общения с сервером (@angular/common/http), которого достаточно для повседневной разработки. Его интерфейс основан на rxjs потоках, поэтому его легко использовать для работы с потоками данных в приложении. Кроме этого, как и в ванильной версии javascript, можно использовать XMLHttpRequest, fetch API, axios(или многие другие библиотеки), но их использование вместо встроенного клиента, считается неоправданным и всячески возбраняется. Существуют и другие способы взаимодействия с сервером(см. Веб-сокеты), но для них не существует каноничных встроенных библиотек, поэтому используются сторонние библиотеки или собственные реалиации. Хорошей практикой здесь будет привести интерфейс построенный на промисах и обратных вызовах(callback) к интерфейсу основанному на rxjs потоках, для естественного использования в экосистеме Angular. Proxy Чтобы тестировать взаимодействие приложения с сервером, который должен находиться на том же домене, используется функциональность в Angular CLI для этого нужно создать файл с конфигурацией прокси, где будут указаны:
Также большинство серверов не настроены для работы с разными доменами(CORS), поэтому для корректной работы на API сервере, необходимо явно указать с какого домена(ов) можно принимать запросы. |
Middle+ or Senior #
Как моделировать loading, error и data state HTTP-запроса?
|
Состояния должны быть взаимоисключающими:
Для signal-first чтения подходят |
Что такое HTTP Interceptors?
|
Interceptor — middleware для общих правил HTTP: auth headers, logging, timeout, retry, caching и индикаторы загрузки. В Angular 19–22 рекомендуются функциональные interceptors: их порядок предсказуем и они могут использовать
Request и response immutable, поэтому запрос изменяют через DI-based |
Angular Router #
Middle+ or Senior #
Чем RouterLink, navigate() и navigateByUrl() отличаются?
Для обычной ссылки используют |
Чем route params, query params и data отличаются?
|
Когда resolver лучше загрузки внутри компонента?
|
Resolver полезен, если route нельзя корректно показать без критических данных или redirect должен произойти до активации. Загрузка внутри компонента лучше, когда:
Ошибку resolver обрабатывают локально через |
Что такое preloading strategy?
|
Preloading загружает lazy chunks после initial navigation, чтобы будущий переход был быстрее.
Preloading не активирует route и не должен бесконтрольно загружать тяжелые admin features мобильному пользователю. |
Что такое nested, auxiliary routes и RouteReuseStrategy?
|
Nested routes отображаются во вложенных Auxiliary routes используют named outlets для независимых UI-областей, например persistent chat или side panel.
|
Как тестировать Angular Router?
|
Для integration-теста используют
Отдельно тестируют functional guards/resolvers как функции в injection context. Проверяют URL, redirect, route inputs и пользовательский результат, а не внутренние Router calls. |
Что такое роутинг и как его создать в Angular?
|
Angular Router связывает URL с деревом активированных routes и компонентов. Современная standalone-конфигурация:
В шаблоне используют
|
Каков жизненный цикл у Angular Router?
|
Основные этапы успешной навигации:
Навигация также может завершиться событиями Современные guards и resolvers являются функциями:
Guard должен вернуть |
Что такое ленивая загрузка (Lazy-loading) и для чего она используется?
|
Lazy-loading откладывает загрузку кода feature до момента, когда пользователь переходит на соответствующий route. Это уменьшает initial bundle и ускоряет первую загрузку.
Lazy-loading не означает, что каждый маленький компонент нужно выделить в отдельный chunk. Границы выбирают по пользовательским сценариям и feature. Для вероятных следующих переходов можно настроить preloading. |
В чем разница между Routing и Navigation?
|
Routing — конфигурация соответствия URL и состояния приложения: routes, параметры, guards, resolvers, outlets, redirects и lazy-loading. Navigation — конкретный процесс перехода из текущего URL/route state в новый. Он может начаться через Во время navigation Router распознает URL, выполняет redirects, guards и resolvers, активирует или переиспользует компоненты, обновляет URL и публикует события. Навигация может завершиться успешно, быть отменена, пропущена или завершиться ошибкой. |
Как загрузить данные до того как активируется роут?
|
Для этого используется resolver. Современный вариант — функция
Router дождется значения или завершения Observable/Promise перед активацией route. Данные доступны через
Resolver подходит, когда экран нельзя корректно показать без данных. Для необязательных или медленных данных лучше активировать страницу сразу и показать loading/skeleton, чтобы навигация не казалась зависшей. |
Управление состоянием #
Junior #
Что такое управление состоянием приложения?
|
Управление состоянием — правила хранения, чтения и изменения данных, от которых зависит UI. Состояние бывает:
Для локального синхронного состояния подходят Хорошее хранилище имеет узкий readonly API, чистые преобразования, явные loading/error/empty states и не дублирует данные, которые можно вычислить. |
Когда достаточно component state?
|
Когда состояние принадлежит одному component subtree: open/closed, выбранная вкладка, черновик формы. Оно легко уничтожается вместе с UI и не создает глобальных зависимостей. При необходимости state можно поднять к ближайшему общему владельцу. |
Middle #
Когда достаточно сервиса с signal?
|
Для синхронного feature state с несколькими consumers и понятными methods обновления. Сервис владеет writable signals и наружу отдает readonly state/computed values. Scope provider определяет lifetime. |
Как не превратить сервис состояния в god object?
|
Разделять state по feature/domain ownership, держать commands узкими и выносить data access отдельно. Не смешивать несвязанные формы, router, HTTP и analytics в одном singleton. Public API должен быть меньше внутренней реализации. |
Middle+ or Senior #
Когда использовать RxJS store service?
|
Когда состояние строится из HTTP, WebSocket, cancellation, debounce и нескольких async streams. RxJS хорошо выражает время, конкуренцию и backpressure. Следует избегать ручных nested subscriptions и скрытого mutable state. |
Что такое facade pattern в Angular state management?
|
Facade предоставляет компонентам узкий API чтения состояния и выполнения use cases, скрывая store/RxJS/HTTP details. Это уменьшает связанность UI с выбранной библиотекой. Facade не должна становиться механическим proxy без domain value. |
В чем отличие между NGRX, NGXS, Akita и какую проблему они решают?
|
Все эти решения помогают организовать общее состояние и предсказуемые изменения, но используют разные модели.
State manager не нужен автоматически. Для небольшого приложения signals и сервисов часто достаточно. Библиотека оправдана, когда сложность координации, отладки и единообразия выше стоимости новой зависимости и дополнительного кода. |
Security #
Middle+ or Senior #
Что такое XSS и как Angular защищает от XSS?
|
XSS, или Cross-Site Scripting, - атака, при которой злоумышленник добивается выполнения своего JavaScript в контексте чужого сайта. Если такой код запустился, он выполняется как код этого сайта: может читать данные страницы, вызывать API от имени пользователя и использовать обычные browser-возможности текущего origin. Ожидаемый ответ на собеседовании: XSS возникает, когда пользовательская строка попадает в HTML/JavaScript context как
код, а не как данные. Самый простой пример без Angular - ручная вставка строки через
Если пользователь откроет учебную ссылку:
браузер может распарсить значение Ожидаемый ответ на вопрос про Безопаснее использовать
Ожидаемый ответ на вопрос про Angular по умолчанию защищает самые частые места вывода данных:
Ожидаемый ответ на вопрос про Angular interpolation:
Такой binding подходит для комментариев, имен пользователей, заголовков и других обычных строк. Если Ожидаемый ответ на вопрос про
Такой binding опасен, если Опасное место -
Особенно опасно применять
Ожидаемый ответ: Ожидаемый ответ на вопрос про обход CSRF: XSS часто опаснее CSRF, потому что XSS-код выполняется уже внутри
Учебный пример:
Если CSRF-token хранится в обычной cookie, которую должен читать frontend, XSS-код на этом же origin тоже может ее
прочитать и отправить header. Backend тоже обязан участвовать в защите:
|
Что такое CSRF?
|
CSRF, или Cross-Site Request Forgery, - атака, при которой злоумышленник заставляет браузер авторизованного пользователя отправить запрос на доверенный сайт. Типичный сценарий:
Если backend проверяет только наличие session cookie и не проверяет CSRF-token, CORS не является полноценной CSRF-защитой. CORS в первую очередь ограничивает чтение ответа JavaScript-кодом из другого origin. Он не гарантирует, что state-changing request вообще не уйдет на сервер. Кроме того, простые requests могут быть отправлены без preflight, а HTML-формы исторически умеют отправлять cross-site POST. Поэтому backend должен отдельно защищать операции изменения состояния. |
Как CSRF-защита выглядит в Angular?
|
Angular
При такой схеме:
Важно: Angular не генерирует CSRF-token и не решает, валиден ли он. Он только переносит значение из cookie в header. Генерация, привязка к сессии, срок жизни и проверка token - ответственность backend. |
Когда создается CSRF-token?
|
CSRF-token создает backend. Обычно token появляется в один из моментов:
Token должен быть случайным, достаточно длинным и непредсказуемым. Обычно он привязан к server-side session или к
подписанному session context. Нельзя использовать захардкоженную строку вроде Пример идеи на backend:
В реальном приложении лучше использовать проверенную CSRF-библиотеку или framework middleware, потому что там уже учтены rotation, session lifecycle и edge cases. |
Чем cookie, HttpOnly cookie и LocalStorage отличаются с точки зрения безопасности?
|
Обычная cookie доступна JavaScript через
CSRF-token cookie часто делают не |
Как использовать Json Web Tokens для аутентификации при разработке на Angular?
|
После входа сервер выдает access token, а клиент прикладывает его к API-запросам:
JWT состоит из header, payload и signature. Payload кодируется, но не шифруется, поэтому туда нельзя помещать секреты. Практическая схема:
Route guard улучшает UX, но не является границей безопасности. Хранение долгоживущего токена в |
Что такое SQL Injection?
|
SQL Injection - атака, при которой пользовательский ввод становится частью SQL-команды. Проблема возникает, когда запрос собирают строкой:
Если
В ORM безопаснее использовать методы, где значения остаются данными:
В TypeORM тот же принцип:
Raw SQL в ORM все равно требует параметров. Нельзя считать ORM автоматической защитой, если разработчик вручную склеивает SQL-строку. |
Почему CORS не является authentication и authorization?
|
CORS, или Cross-Origin Resource Sharing, - browser mechanism, который определяет, может ли JavaScript с одного origin
прочитать ответ от другого origin. Сервер управляет этим через Главная мысль: CORS ограничивает чтение ответа браузером, а не заменяет authentication и authorization. Если endpoint доступен без проверки прав, правильные CORS headers его не спасут. Если пользователь авторизован cookie, browser может отправить запрос на нужный domain, поэтому для mutating операций все равно нужна CSRF-защита.
|
Что такое CSP?
|
CSP, или Content Security Policy, - HTTP header, который сообщает браузеру, откуда можно загружать scripts, styles, images, fonts, frames и другие ресурсы. CSP снижает риск XSS: даже если в HTML попал вредоносный fragment, строгая policy может запретить inline script или загрузку script с неизвестного домена. Минимальный пример:
На практике policy часто шире: добавляют |
Что такое authorization check на backend?
|
Authorization check - серверная проверка, имеет ли текущий пользователь право выполнить действие или прочитать ресурс. Frontend guards, скрытые кнопки и disabled controls улучшают UX, но не являются защитой: пользователь может вызвать API напрямую через browser devtools, curl или измененный frontend. Backend обязан проверять права на каждый чувствительный endpoint. Классический пример IDOR:
Если пользователь с id
|
Что такое OWASP?
|
OWASP - открытое сообщество и набор практических материалов по безопасности приложений. Frontend-разработчику полезны OWASP Top 10, ASVS и Cheat Sheet Series. Это не scanner и не готовая сертификация, а база рисков, требований и рекомендаций. |
Какие меры защиты должен знать frontend-разработчик?
|
Frontend-разработчику важно понимать, где заканчивается клиентская ответственность и начинается обязательная серверная проверка. Клиентская validation нужна для UX, но доверять можно только backend validation. Базовый набор backend-защит:
Безопасность является общей ответственностью frontend, backend и инфраструктуры. |
Performance #
Middle+ or Senior #
Как performance budget применяется в Angular-проекте?
|
В Angular performance budget обычно включает размер initial bundle, lazy chunks, CSS, LCP, CLS, INP и время до интерактивности. Angular CLI поддерживает budgets для build artifacts, но этого недостаточно: нужно также измерять Web Vitals на реальных страницах, следить за lazy routes, standalone imports, third-party dependencies и SSR/hydration поведением. |
Как уменьшать размер frontend assets в Angular?
|
Основные способы: lazy routes, |
Как искать проблему производительности в Angular-приложении?
|
Порядок работы:
Не следует начинать с |
Что такое initial bundle и как уменьшить bundle size?
|
Initial bundle — JavaScript/CSS, необходимые для первой загрузки route. Способы уменьшения:
Размер gzip/brotli важен, но также измеряют parse, compile и execution time. |
Что такое @defer и чем он отличается от lazy route?
|
Lazy route откладывает целую route feature до навигации.
Triggers включают |
Как оптимизировать большие списки?
Virtual scroll нужен, когда DOM и rendering, а не загрузка данных, являются bottleneck. Для переменной высоты элементов он сложнее и требует измерений. |
Как Angular-приложение может создавать лишние render и change detection cycles?
|
Частые причины: частые events без ограничения, timers, подписки без фильтрации, template methods с тяжелой логикой,
изменение global state и обновления сигналов слишком высоко в дереве. В zone-based приложении async tasks могут
провоцировать широкую синхронизацию, а в zoneless код должен явно обновлять реактивные источники. Диагностируют это
через Angular DevTools Profiler и Chrome Performance, затем локализуют state, добавляют |
Как lazy loading влияет на performance Angular-приложения?
|
Lazy routes и |
Как virtual scroll помогает большим спискам в Angular?
|
Virtual scroll держит в DOM только видимую часть списка и небольшой buffer, поэтому уменьшаются layout, paint, memory usage и change detection work. Он полезен для сотен или тысяч однотипных строк, но усложняет variable height, focus, keyboard navigation и screen reader experience. Если bottleneck в API или фильтрации данных, virtual scroll не решит корневую проблему. |
Почему в performance-аудите проверяют sideEffects библиотек?
|
Если библиотека не публикует ESM, содержит широкий entry point или неправильно описывает side effects, unused code может
остаться в initial bundle. Обратная ошибка тоже опасна: неверное Поэтому в performance-аудите проверяют не только размер dependency, но и ее |
Как анализировать Angular bundle?
|
Используют:
Ищут крупные dependencies, дубликаты, случайно eager-loaded features, locale/data imports и библиотеки, которые можно заменить browser API или точечным import. |
SSR, hydration и SEO #
Middle+ or Senior #
Как frontend guidelines помогают SSR, hydration и SEO в Angular?
|
Guidelines фиксируют, какие страницы рендерятся через SSR или prerender, как подключаются critical CSS, fonts и media, какие browser-only API нельзя вызывать во время server rendering и как проверяется hydration. Это снижает риск пустого first render, layout shifts, hydration mismatch и случайного ухудшения SEO. |
Чем CSR, SSR и SSG отличаются?
SSR подходит динамическим SEO-страницам, SSG — статичному контенту, CSR — внутренним приложениям без SEO. Angular поддерживает hybrid route-level render modes. |
Что такое hydration в Angular и какие проблемы она решает?
|
Hydration подключает Angular к уже существующему server-rendered DOM вместо полного пересоздания. Сервер отдает HTML, пользователь видит содержимое до полной загрузки JavaScript, а Angular на клиенте сопоставляет этот DOM со своими компонентами, восстанавливает bindings и подключает обработчики событий. Плюсы:
Пример настройки:
В Angular 22 HTML сервера и клиента должен быть детерминированным, иначе возникает hydration mismatch. Типичные причины: прямой
доступ к |
Почему browser-only код нельзя выполнять на сервере?
|
На сервере browser globals отсутствуют. Безопасные варианты:
Компонент не должен генерировать разный initial DOM на сервере и клиенте без предусмотренного механизма. |
Что такое TransferState и HTTP transfer cache?
|
TransferState передает сериализованные данные из server render клиенту, чтобы не повторять запрос сразу после hydration. Angular SSR интегрирует transfer cache с |
Когда SSR не нужен?
|
SSR может не окупиться для:
SSR улучшает delivery HTML, но не уменьшает автоматически client JavaScript. Решение принимают по SEO, Core Web Vitals, инфраструктуре и пользовательскому сценарию. |
Как SSR, hydration и prerender помогают Angular-приложению?
|
SSR отдает HTML на каждый запрос и помогает динамическим SEO-страницам, previews и first paint. Prerender генерирует статические routes заранее и хорошо подходит для документации, landing pages и публичного контента. Hydration сохраняет server-rendered DOM и подключает к нему Angular на клиенте, уменьшая flicker и риск лишней перерисовки. |
Какие проблемы могут возникать при hydration в Angular?
|
Основная проблема — hydration mismatch, когда server HTML не совпадает с первым client render. Причины: browser-only globals во время render, случайные значения, даты и timezone, разные данные на сервере и клиенте, direct DOM mutation или third-party widget до завершения hydration. Такие места изолируют, делают rendering детерминированным или переносят browser-only работу в безопасную client-only фазу. |
Как Angular-приложение может избежать FOUC или плохого first render?
|
Нужны server-rendered или prerendered HTML, critical CSS, стабильные fallback fonts, корректные размеры media, ранняя
загрузка LCP resource и отсутствие базовых стилей, которые приезжают только после JavaScript. Для Angular также важно,
чтобы global styles и component styles были доступны при первом render, а placeholders для |
В чем разница между Angular CLI и Webpack Development Environment?
|
Angular CLI — официальный интерфейс для создания, запуска, тестирования, обновления и сборки Angular-проектов. Он управляет workspace-конфигурацией и вызывает настроенный builder. Webpack — универсальный bundler. Исторически Angular CLI использовал Webpack внутри, но это деталь реализации: современные builders могут использовать другие инструменты, например esbuild/Vite-based development server. CLI дает:
Ручная Webpack-конфигурация дает больше низкоуровневого контроля, но увеличивает стоимость поддержки и обновлений. В Angular-проекте сначала используют возможности CLI и custom builder, а eject/собственный pipeline выбирают только при реальной необходимости. |
Что такое JIT и AOT, в чем их отличия и каковы сферы применения?
|
AOT компилирует templates и decorators во время сборки. В современных Angular CLI проектах AOT является стандартным
режимом и для Плюсы AOT:
JIT компилирует Angular declarations во время выполнения. Он нужен редко: для специальных динамических сценариев, tooling или legacy-конфигураций. Для обычной разработки переключаться на JIT не требуется.
|
Angular PWA и Service Worker #
Middle+ or Senior #
Как Angular помогает с localization?
|
Angular предоставляет i18n-инструменты для извлечения и подстановки переводов, а также pipes для дат, чисел и валют с учетом locale. Но команда все равно должна решить, где хранятся переводы, нужен ли runtime или build-time localization, как тестируются языки и как компоненты переживают длинные строки, pluralization и RTL. |
Почему RTL нужно учитывать в layout и компонентах?
|
RTL меняет направление текста и часто влияет на icons, arrows, spacing, alignment, keyboard navigation и animations. Нельзя просто перевести строки и считать интерфейс готовым. Компоненты design system должны явно поддерживать LTR/RTL, а CSS должен использовать logical properties там, где это упрощает поддержку. |
Для чего нужны service worker?
|
Service Worker — это фоновый слой между сайтом и сетью. Service Worker — это JavaScript-файл, который браузер запускает отдельно от страницы. Он может перехватывать сетевые запросы, работать с кешем, получать push-уведомления и помогать сайту работать офлайн. |
Для чего нужен PWA и какие плюсы?
|
PWA — это сайт, который ведет себя почти как приложение PWA = Progressive Web App. Это обычное веб-приложение, но с дополнительными возможностями:
Для чего нужен PWA: PWA нужен, когда ты хочешь дать пользователю app-like experience, но без полноценной разработки под iOS/Android. Главные плюсы PWA:
Пользователь может нажать “Add to Home Screen” и получить иконку приложения. Плюс для бизнеса:
PWA может кешировать:
Может работать офлайн Например:
Это особенно полезно для:
Push-уведомления: PWA может отправлять уведомления, например: “Заказ доставлен”; “Новая задача”; “Скидка”; “Напоминание”; “Документ согласован”. Когда PWA подходит PWA хорошо подходит, если:
CRM, todo app, dashboard, docs, e-commerce, booking app Когда PWA не лучший выбор PWA хуже подходит, если нужны:
|
Какую роль в PWA играет Service Worker?
|
Service Worker — это JS-файл, который браузер запускает отдельно от страницы и который стоит “между” приложением и сетью. Как работает обычный сайт: Page -> Network -> Server PWA с Service Worker: Page -> Service Worker -> Cache / Network -> Server Service Worker может перехватывать запросы: Пользователь открыл страницу ↓ Браузер спрашивает Service Worker ↓ SW решает:
Ты открыл сайт первый раз:
Service Worker может сохранить эти файлы в Cache Storage. Потом пользователь открывает сайт без интернета: нет сети ↓ Service Worker берет файлы из кеша ↓ приложение все равно открывается Для чего он нужен в PWA
Service Worker не имеет доступа к DOM. Он живет отдельно от страницы. Страница и Service Worker общаются через события/messages. Service Worker нужен в PWA, чтобы приложение могло кешировать ресурсы, быстрее загружаться, работать офлайн и получать push-уведомления. |
Testing #
Middle+ or Senior #
Какие вопросы задать про тестирование Angular-кода в команде?
|
Нужно понять, какие уровни тестов используются: unit, integration, component, e2e и visual regression. Также важно выяснить, какие инструменты приняты: TestBed, Angular Testing Library, Component Harness, Cypress, Playwright, Jest, Vitest или Karma. Хороший ответ объясняет не только инструменты, но и что именно ими проверяют и где проходит граница между тестом, lint и ручной проверкой. |
Какие виды тестирования используют в Angular?
В Angular unit/integration-тесты обычно используют TestBed, spies/fakes, HTTP testing utilities и Router testing harness. E2E выполняют Playwright или Cypress. Основу набора составляют быстрые unit и integration-тесты. E2E оставляют для критических сквозных сценариев: вход, checkout, создание сущности. Тестируют наблюдаемое поведение, а не приватные методы и внутреннюю структуру компонента. |
Какие плюсы у тестирования frontend-кода?
|
Тесты быстро ловят regressions, фиксируют ожидания компонента или сервиса и помогают безопасно менять код. В Angular они особенно полезны для forms, routing, DI, HTTP mapping, guards, pipes и сложных states. Хорошие тесты уменьшают страх перед refactoring, но не заменяют ручную проверку UX и accessibility. |
Какие минусы и trade-offs у тестов?
|
Тесты требуют времени на написание и поддержку, могут быть хрупкими и иногда закрепляют плохую архитектуру. Избыточные mocks проверяют реализацию вместо поведения, а слишком много E2E замедляет feedback. Зрелый подход выбирает уровень теста по риску: чистую функцию проверять unit-тестом, пользовательский сценарий — integration или E2E. |
Какие инструменты использовать для тестирования Angular-кода?
|
Для Angular обычно используют TestBed, Angular testing utilities, |
Чем unit test отличается от integration test?
|
Unit test проверяет небольшую единицу с изолированными зависимостями: функцию, pipe, mapping или сервис. Integration test проверяет совместную работу нескольких частей: компонент с template, DI, Router, forms или HTTP testing layer. В Angular многие полезные component tests фактически являются integration tests, и это нормально. |
Чем integration test отличается от e2e test?
|
Integration test запускает часть приложения в тестовой среде и контролирует зависимости. E2E test открывает приложение в реальном браузере и проверяет пользовательский путь через UI, часто с network layer, auth и routing. E2E дает больше уверенности в сценарии, но медленнее и дороже в поддержке. |
Какие testing best practices важны во frontend?
|
Проверять observable behavior, использовать role/label/test id selectors, избегать sleeps, стабилизировать данные и тестировать loading/error/empty states. Не стоит проверять private methods, случайные CSS classes и внутреннее число signals. Тест должен падать по понятной причине и помогать найти regression. |
Когда тестировать компонент через DOM, а когда тестировать чистую функцию?
|
Если контракт виден пользователю или другому компоненту через template, events, forms или accessibility, лучше проверять через DOM. Если логика является чистым преобразованием данных, ее проще и быстрее тестировать как функцию. Хороший дизайн часто выносит сложные вычисления из компонента, оставляя DOM-тесту только интеграцию. |
Что лучше тестировать в Angular service?
|
В service тестируют mapping DTO в domain model, обработку ошибок, cache/invalidation, retries, guards against invalid
input и взаимодействие с HTTP или storage через контролируемые fakes. Не нужно тестировать сам |
Когда использовать Angular Testing Library, TestBed, Component Harness, Cypress или Playwright?
|
TestBed — базовый инструмент Angular для DI, components и services. Angular Testing Library удобна для behavior-first component tests через DOM queries. Component Harness нужен для стабильного тестового API reusable UI components. Cypress и Playwright используют для browser-level сценариев; Playwright особенно силен в multi-browser, tracing и parallel execution. |
Какие тесты чаще всего получаются хрупкими?
|
Хрупкими становятся тесты на CSS classes, внутреннюю структуру DOM, private methods, точные timers, реальные внешние API, порядок независимых async events и snapshots больших компонентов. Их чинят через стабильные locators, ожидание видимого состояния, deterministic data, fakes и перенос логики в тестируемые чистые функции. |
Что тестировать в Angular-компоненте, а что не нужно?
|
Тестируют публичное поведение:
Не тестируют Angular framework, private methods, внутреннее количество signals или точную структуру реализации без контрактной причины. |
Как тестировать standalone component и мокать service?
Standalone component добавляют в |
Как мокать Angular module в тесте?
|
Если тестируемый компонент зависит от NgModule-based library, можно импортировать настоящий testing module или заменить тяжелую зависимость lightweight stub component/directive/pipe. Для standalone components часто проще использовать |
Как тестировать сервис с async dependency?
|
Async dependency заменяют stub/fake, который возвращает контролируемый Promise или Observable. Тест должен явно
дождаться результата через Для HTTP-зависимостей используйте |
Чем spy, fake, stub и mock отличаются?
|
В Angular-тестах чаще достаточно stub/fake service и проверки observable behavior через DOM или публичный API. |
Как тестировать content projection?
|
Создайте host test component, который использует тестируемый компонент как реальный потребитель и передает projected content между tags. Так проверяются slots, selectors, content queries и пользовательский результат, а не внутренние детали реализации компонента. |
Чем fakeAsync/tick отличается от waitForAsync?
|
|
Как тестировать CVA и формы?
|
CVA лучше тестировать через host form:
Отдельный вызов методов CVA не заменяет integration-тест с |
Почему E2E-тесты флакают и как уменьшить flaky tests?
|
Причины: sleeps, нестабильные данные, race conditions, animation, зависимость от порядка, слабые selectors. Решения:
Behavioral assertions важнее screenshot tests; screenshots полезны для ограниченного visual regression. |
Как организовать frontend tests в CI?
|
Обычно:
Тесты параллелят, кешируют dependencies/build, сохраняют trace и разделяют быстрый PR pipeline с более широким nightly suite. |
Что такое Karma, Jasmine (зачем их используют совместно при разработке на Angular)?
|
Это разные части тестового стека:
Их использовали совместно, потому что Jasmine описывал тесты, а Karma предоставлял браузерное окружение и запуск. Это исторически популярная конфигурация Angular CLI, но не единственный современный вариант. Проект может использовать Vitest, Jest или другой runner. При выборе важны скорость, browser fidelity, поддержка Angular, debugging и интеграция с CI. |
В чем разница между Jest и Karma?
|
Сравнение не полностью симметрично:
Jest часто быстрее и проще для unit-тестов благодаря параллельному запуску, watch mode и встроенным инструментам. Karma дает настоящее браузерное окружение, но обычно запускается и настраивается тяжелее. Эмуляция DOM не воспроизводит все особенности layout, CSS и browser API. Поэтому даже при Jest/Vitest нужны component integration и E2E-тесты в реальном браузере для поведения, зависящего от платформы. |
В чем разница между Protractor и Cypress?
|
Protractor был Angular-ориентированным E2E-инструментом поверх WebDriver и умел автоматически ожидать Angular stability. Проект Protractor снят с поддержки и не должен выбираться для новых приложений. Cypress работает через собственный browser runner, дает удобный time-travel UI, автоматические ожидания, network stubbing и хорошую диагностику. Его модель выполнения отличается от обычного WebDriver и имеет собственные ограничения, например при работе с несколькими вкладками и некоторыми cross-origin сценариями. Современная альтернатива также Playwright: он управляет Chromium, Firefox и WebKit, поддерживает несколько контекстов, вкладок и параллельный запуск. Для существующего проекта миграция должна сохранять критические сценарии и постепенно заменять Protractor-тесты, а не переписывать весь набор одним большим изменением. |
Как протестировать входные параметры и всплывающие события компонентов?
|
Лучше тестировать компонент через его публичный API и DOM.
Для signal input используется тот же После изменения input нужно запустить change detection. Не следует напрямую вызывать приватные методы: клик по доступной кнопке лучше отражает контракт компонента. |
Angular coding questions #
Middle+ or Senior #
Что отрендерит компонент с ContentChildren, Directive, QueryList, *ngIf и projected content?
|
Короткий ответ: отрендерится |
Angular libraries и design systems #
Middle+ or Senior #
Как guidelines помогают design system в Angular?
|
Guidelines связывают компоненты design system с реальным использованием в продуктах: naming, inputs/outputs, accessibility, theming, tokens, layout patterns и правила расширения. Это снижает количество кастомных fork-like решений и помогает разным командам использовать UI kit одинаково. |
Почему Angular-команде важно документировать отклонения от UI kit или framework?
|
Отклонения появляются из-за нестандартных требований, legacy-кода или ограничений продукта. Если их не документировать, новые разработчики будут копировать workaround как норму. Хорошая документация объясняет причину, область применения и условия, при которых workaround можно удалить. |
Что такое pattern library и зачем она нужна?
|
Pattern library описывает повторяемые UI patterns, компоненты, states, accessibility rules и примеры использования. В Angular-мире эту роль часто выполняют Storybook, Docusaurus, documentation site design system или собственные examples. Она помогает продуктовым командам не изобретать один и тот же интерфейс заново. |
Чем library code отличается от application code?
|
Application знает конкретный продукт, routes, backend и окружение. Library должна работать в разных приложениях и версиях конфигурации. Для библиотеки важнее:
|
Что такое public API Angular library и почему нельзя экспортировать все?
|
Public API — imports, components, directives, tokens и types, которые библиотека обещает поддерживать. Экспорт внутренних helpers:
Потребители импортируют только из package entry points, а не из внутренних путей. |
Что такое breaking change и как версионировать библиотеку?
|
Breaking change требует изменения кода потребителя: удаление export, изменение selector/input, поведения, CSS contract или поддерживаемых версий. Semantic Versioning:
Перед major нужны deprecation period, migration guide, schematics и automated tests совместимости. |
Почему Angular должен быть peerDependency библиотеки?
|
Диапазон peer dependency должен отражать реально протестированные версии. Runtime dependencies оставляют только для библиотек, которые действительно должны поставляться вместе с package. |
Как проектировать конфигурируемый Angular-компонент?
|
Локальные параметры передают inputs. Общую конфигурацию библиотеки предоставляют через typed
Defaults должны быть явными, config — readonly, а локальный input может переопределять глобальное значение. Не следует превращать один компонент в десятки boolean flags; варианты моделируют union types. |
Как проектировать theme, icon и overlay API?
Для overlay primitives предпочтителен Angular CDK, если библиотека не решает более низкоуровневую задачу. |
Что такое secondary entry points и когда они нужны?
|
Secondary entry point позволяет импортировать отдельную область:
Он полезен для независимых feature packages и optional dependencies. Слишком много entry points увеличивает build, release и compatibility surface. Entry points не должны образовывать cycles и импортировать внутренности друг друга в обход публичных границ. |
sideEffects в package.json и tree shaking #
Middle+ or Senior #
Что такое tree shaking?
|
Tree shaking — это оптимизация сборки, при которой bundler удаляет неиспользуемый код из итогового bundle. Лучше всего
это работает с ES modules, потому что Пример: если приложение импортирует только |
Что такое side effect в JavaScript-модуле?
|
Side effect — это действие, которое происходит просто при импорте модуля, даже если его exports не используются. Примеры side effects:
Модуль с side effect:
Модуль без side effects:
|
Что делает "sideEffects": false в package.json?
|
Пример:
|
Почему "sideEffects": false помогает уменьшить bundle size?
|
Bundler не всегда может сам понять, безопасно ли удалить импортируемый модуль. Флаг Для shared package это особенно полезно, когда приложение использует один |
Почему этот флаг особенно важен для библиотек?
|
Библиотеки часто содержат много независимых компонентов, функций и entry points. Потребитель может импортировать только
одну часть библиотеки, и bundler должен иметь возможность удалить остальное. Для Angular library это важно вместе с ESM output, secondary entry points, tree-shakable providers и аккуратными public exports. |
Чем опасен неправильный "sideEffects": false?
|
Если пакет помечен как side-effect-free, но внутри есть важные side effects, bundler может удалить нужный код. Ошибка может проявиться только в production build: например, пропадут стили, не зарегистрируется polyfill или не выполнится initialization logic. Риск особенно неприятен для UI libraries: компонент может собраться без ошибок, но визуально сломаться из-за удаленного CSS import. |
Какие файлы нельзя бездумно считать side-effect-free?
|
Осторожно с файлами, которые:
Пример:
Такой файл имеет side effects. |
Что делать, если в пакете есть и pure modules, и файлы с side effects?
|
Можно указать не Пример:
Так bundler сможет удалять pure modules, но сохранит файлы, которые важны из-за side effects. |
Почему CSS imports часто указывают в sideEffects?
|
CSS import нужен не ради JavaScript export, а ради самого факта подключения стилей. Если bundler удалит такой import, UI может сломаться. Пример:
Для design system это часто безопаснее, чем глобально ставить |
Как выглядит пример pure package?
|
Pure package экспортирует функции или значения и не выполняет важный код при импорте.
Если приложение использует только |
Как выглядит package с CSS side effect?
Если поставить Безопаснее:
|
Почему barrel file может неожиданно иметь side effect?
|
Barrel file выглядит как простой public API, но любой top-level import в нем выполняется при импорте entry point.
Такой |
Как sideEffects связан с Angular providers?
|
Фабрики providers обычно не являются side effects, если они просто экспортируются из файла. Side effect появляется, если код выполняется сразу при импорте модуля, а не тогда, когда Angular реально использует provider. Пример без top-level side effect:
|
Почему важно не выполнять тяжелую логику на top-level в Angular library?
|
Top-level код выполняется сразу при импорте модуля. Это может мешать tree shaking, SSR и тестам. Для библиотек лучше экспортировать функции, providers, классы и components, а выполнение логики оставлять приложению. Плохо:
Лучше:
|
Почему пакет может попадать в bundle, хотя его компонент напрямую не используется?
|
Возможные причины:
Проверять нужно dependency graph и реальные imports consumer-приложения, а не только исходный код компонента. |
Как проверить, что "sideEffects": false реально уменьшает bundle?
|
Нужно собрать production build и сравнить bundle stats до и после изменения. Можно использовать:
Важно проверять не только размер bundle, но и работоспособность приложения: стили, SSR, lazy loading и initialization logic. |
Как проектировать библиотеку, чтобы она хорошо tree-shaking-илась?
|
Как secondary entry points помогают bundle size?
|
Secondary entry points позволяют импортировать отдельные части библиотеки:
Это может быть лучше, чем один большой entry point, который тянет много лишнего кода. Secondary entry points полезны, когда части пакета независимы: например, |
Как безопасно добавить "sideEffects": false в библиотеку?
Главная идея: сначала доказать, какие файлы действительно pure, и только потом менять |
Что спросить на code review, если в PR добавляют "sideEffects": false?
|
Стоит проверить не только уменьшение bundle size, но и безопасность изменения:
На review важно просить evidence: stats, production build и короткий список файлов, которые считаются side-effectful. |
Какой короткий вывод по sideEffects и tree shaking?
|
|
Зачем Angular library нужны migrations и schematics?
|
Schematics автоматизируют изменения workspace и consumer code. Migration нужна, когда новая версия меняет API, selectors, imports или конфигурацию. Хорошая migration:
|
Как документировать и тестировать component library?
|
Для каждого public component нужны:
Тестируют behavior, harness API, forms integration, overlays, SSR и visual states. Demo/documentation app одновременно служит integration consumer, но не заменяет automated tests. |
Почему "sideEffects": false не заменяет хорошую архитектуру пакета?
|
Этот флаг только дает bundler подсказку. Если пакет устроен как один большой entry point с тяжелыми imports, неаккуратными barrels и top-level initialization, tree shaking все равно может быть хуже. Хорошая библиотека должна быть спроектирована для статического анализа. Практичный ориентир: consumer должен иметь возможность импортировать маленькую часть API без загрузки всего |
Micro Frontends #
Практический пример: examples/angular/mfe.
В этом демо можно увидеть:
- host/shell приложение
movie-ticket; - remote widgets
moviesиticket-availability; - federation manifest и
remoteEntry.json; - runtime loading и host orchestration через Angular inputs/outputs;
- независимые loading/error states и fallback UI;
- SSR-safe browser-only mounting через
afterNextRender().
Инструкции по запуску находятся в examples/angular/mfe/.
Базовые понятия
Middle+ or Senior #
Что такое микрофронтенды и какую проблему они решают?
|
Микрофронтенды разделяют frontend на автономные части, за которые могут отвечать разные команды. Они помогают независимо разрабатывать и выпускать крупные продуктовые области, но добавляют распределенные контракты, инфраструктуру и риски времени выполнения. |
Чем микрофронтенд отличается от обычного lazy-loaded Angular route?
|
Lazy route остается частью одной сборки и одного release-процесса. Микрофронтенд может собираться, размещаться и загружаться отдельно, поэтому его версия и доступность не обязательно совпадают с host. |
Что такое shell/host application?
|
Host — приложение-контейнер. Оно задает общий layout, навигацию, интеграционные контракты и загружает remote-модули или виджеты, а также обрабатывает их loading и error states. |
Что такое remote application?
|
Remote — отдельно собираемое приложение, которое публикует доступные host части через federation metadata. Оно должно иметь явный публичный контракт и по возможности не зависеть от внутренних деталей host. |
Когда микрофронтенды оправданы, а когда это лишнее усложнение?
|
Они оправданы при нескольких автономных командах, независимых release cycles и устойчивых domain boundaries. Для небольшой команды, единого продукта и общего деплоя modular monolith обычно дешевле и надежнее. |
Почему микрофронтенды часто сложнее монолита?
|
В монолите компилятор и единая сборка проверяют большую часть связей заранее. В микрофронтендах часть ошибок проявляется только при интеграции конкретных независимо развернутых версий через сеть. |
Что такое independent deployment?
|
Это возможность выпустить remote без обязательной пересборки и публикации host или других remote. Для этого нужны совместимые контракты, отдельные pipelines, контролируемые URL и стратегия rollback. |
Какие границы микрофронтендов бывают: route-level, widget-level, domain-level?
|
Route-level делит приложение по страницам, widget-level встраивает независимые блоки в одну страницу, domain-level следует бизнес-областям. Domain boundary описывает ответственность, а route и widget — способ композиции UI. |
Чем route-level federation отличается от widget-level federation?
|
Route-level загружает крупный экран при навигации и обычно проще изолирует команды. Widget-level компонует несколько remote на одной странице, поэтому требует более точной оркестрации, layout-контрактов и независимых состояний ошибки. |
Какие минусы есть у микрофронтенд-архитектуры?
|
Основные минусы: сложнее локальная разработка, тестирование, наблюдаемость, versioning, shared state, согласование UX, SSR и rollback. Также возможны дубли dependencies и дополнительная задержка runtime-загрузки. |
Native Federation и runtime loading
Middle+ or Senior #
Что такое Native Federation?
|
Native Federation — подход к runtime-композиции приложений на основе стандартных ES modules и import maps. Инструменты генерируют metadata и согласуют shared dependencies, а браузер загружает модули без webpack runtime. |
Что такое remoteEntry.json?
|
Это сгенерированный entry-файл remote с описанием exposed modules, shared packages и связанных chunks. Host читает его, чтобы понять, откуда загрузить запрошенный export. |
Что такое federation manifest?
|
Manifest — карта логических имен remote на URL их |
Зачем host-приложению нужен manifest remote-приложений?
|
Host использует manifest для разрешения имени remote в конкретный URL. Один и тот же build host может получать разные адреса для local, stage, production или canary окружений. |
Чем runtime-загрузка remote отличается от обычного static import?
|
Static import известен во время сборки и попадает в dependency graph общего bundle. Runtime-загрузка разрешает модуль после запуска приложения, поэтому требует сетевой обработки ошибок и runtime-проверки контракта. |
Что делает initFederation()?
|
|
Что делает loadRemoteModule()?
|
|
Что такое shared dependencies?
|
Это packages, которые host и remotes договариваются использовать совместно вместо загрузки отдельных копий. Sharing уменьшает bundle, но требует совместимых версий и корректной настройки singleton-пакетов. |
Зачем нужны singleton, strictVersion и requiredVersion?
|
|
Что может пойти не так, если host и remote используют разные версии Angular?
|
Возможны несовместимые runtime contracts, несколько Angular instances, ошибки DI, rendering и signals. Допустимость версий должна проверяться federation-конфигурацией, CI и integration tests. |
Почему Angular и RxJS обычно шарят как singleton?
|
Angular ожидает согласованный framework runtime и injector graph, а разделяемые RxJS-контракты проще поддерживать с одной совместимой копией. Несколько версий увеличивают bundle и риск несовместимости типов и поведения. |
Что такое import map?
|
Import map сопоставляет bare module specifiers с URL ES modules в браузере. Native Federation может формировать такую карту для shared packages и remote-зависимостей. |
Почему браузер может не зарезолвить bare specifier вроде @softarc/native-federation-orchestrator?
|
Браузер не знает npm resolution. Для bare specifier должен существовать import map или bundler-преобразование; иначе возникает ошибка разрешения модуля. Также import map должна быть загружена до первого import. |
Почему deprecated API не всегда означает, что код немедленно сломан?
|
Deprecated API пока может оставаться совместимым, но больше не рекомендуется и может быть удален позже. Нужно проверить версию, migration path и фактическое поведение, а не заменять API вслепую. |
Dynamic components
Middle+ or Senior #
Как динамически создать Angular-компонент через ViewContainerRef.createComponent()?
|
Нужно получить |
Что такое ComponentRef?
|
|
Как передать input в динамически созданный компонент?
|
После создания вызывают |
Почему ComponentRef.setInput() лучше прямого присваивания свойства?
|
|
Как подписаться на output динамически созданного компонента?
|
Нужно получить публичный output с |
Как правильно уничтожать динамически созданные компоненты?
|
Компонент уничтожают через |
Зачем хранить ComponentRef и вызывать destroy()?
|
Ссылка нужна для последующих inputs, подписки на outputs и явного lifecycle management. Без уничтожения могут остаться view, subscriptions и ссылки на данные, что приводит к утечкам и повторной обработке событий. |
Почему viewChild.required() нельзя вызывать слишком рано?
|
Query signal получает значение только после создания соответствующего элемента view. Чтение до завершения render приведет к ошибке required query, поэтому DOM-зависимую работу откладывают до подходящей render phase. |
Зачем иногда передают getContainer: () => ViewContainerRef, а не сам ViewContainerRef?
|
Функция откладывает чтение query до момента фактического монтирования. Это полезно, когда loader настраивается раньше, чем Angular создал template container. |
Коммуникация между remote-приложениями
Middle+ or Senior #
Как remote-приложения могут общаться между собой?
|
Через host orchestration, URL, backend, shared event bus или browser events. Выбор зависит от lifetime состояния, необходимости deep link, надежности и допустимой связанности между командами. |
Почему прямое общение remote-to-remote может быть проблемой?
|
Один remote начинает знать API и lifecycle другого, из-за чего их нельзя независимо заменить или загрузить. Такая связь также усложняет versioning, тестирование и обработку частичной недоступности. |
Что такое host orchestration?
|
Host принимает события remote, применяет общую бизнес-навигацию и передает данные другим remote через их публичные контракты. Remote при этом не импортируют и не ищут друг друга напрямую. |
Как host может связать output одного remote с input другого remote?
|
Host подписывается на output первого |
Чем CustomEvent отличается от Angular output() / input() через host?
|
Angular inputs/outputs типизированы и привязаны к component lifecycle. |
Какие плюсы и минусы у коммуникации через window.dispatchEvent()?
|
Плюсы — слабая технологическая связанность и простой межфреймворковый transport. Минусы — глобальное пространство имен, слабая типизация, неявный поток данных, ручная очистка listeners и отсутствие browser globals при SSR. |
Почему window.addEventListener() может быть проблемой при SSR?
|
На сервере |
Когда стоит использовать shared event bus?
|
Когда нескольким независимо загружаемым частям нужен ограниченный набор асинхронных domain events. Bus должен иметь версионированные типы, владельца и правила lifecycle, иначе он быстро превращается в неявное глобальное состояние. |
Когда лучше использовать URL/query params для состояния?
|
Для состояния навигации, фильтров и выбранных сущностей, которое должно поддерживать deep link, back/forward и перезагрузку страницы. Секретные или большие данные в URL помещать не следует. |
Когда состояние лучше хранить на backend?
|
Когда оно должно переживать сессии, быть общим для устройств или пользователей, участвовать в транзакциях и иметь серверную авторизацию. Frontend тогда хранит только идентификатор и локальное представление. |
Почему для микрофронтендов важны явные контракты?
|
Remote выпускаются независимо, поэтому inputs, outputs, exposed modules и payload schemas заменяют compile-time связь. Явные контракты можно версионировать, тестировать и сохранять совместимыми. |
Loading, error states и fallback
Middle+ or Senior #
Что произойдет, если один remote недоступен?
|
Его entry или chunks не загрузятся, и операция вернет ошибку. Host должен локализовать сбой в соответствующем slot, показать fallback и не блокировать независимые части страницы. |
Чем required remote отличается от optional remote?
|
Без required remote основной сценарий не имеет смысла, поэтому host может показать page-level error. Optional remote дополняет сценарий: при сбое его slot скрывают или заменяют fallback, сохраняя остальную страницу. |
Почему Promise.all() может быть опасен при загрузке нескольких независимых remote?
|
Он отклоняется после первой ошибки и не возвращает успешные результаты остальных promises. Если виджеты независимы, общая операция может ошибочно превратить частичный сбой в отказ всей композиции. |
Когда лучше использовать Promise.allSettled()?
|
Когда каждый remote имеет собственный loading/error state и успешные виджеты должны продолжить работу. Результаты
|
Как host должен показывать loading/error state для каждого remote slot?
|
Каждый slot имеет стабильный контейнер, собственный индикатор загрузки, доступное сообщение об ошибке и при необходимости retry. Ошибка одного slot не должна визуально маскировать состояние другого. |
Почему у каждого remote widget должен быть свой status: idle, loading, ready, error?
|
Явная state machine исключает неоднозначные комбинации boolean flags и упрощает template control flow. Она также позволяет отдельно измерять время загрузки, ошибки и повторные попытки каждого remote. |
Что должен делать host, если movies загрузился, а ticket-availability нет?
|
Показать список фильмов и fallback в slot доступности. Выбор фильма можно сохранить, но действие, зависящее от второго remote, нужно отключить или объяснить пользователю. |
Что должен делать host, если ticket-availability загрузился, а movies нет?
|
Показать fallback списка фильмов. Виджет доступности может остаться в empty state, если без выбранного фильма он не имеет самостоятельного сценария. |
Как добавить retry для недоступного remote?
|
Host повторно переводит конкретный slot в |
Где лучше хранить статусы remote-виджетов: в компоненте, сервисе или store?
|
Локальный slot state удобно хранить в host component или scoped loader service. Общий store нужен только если статус используют удаленные части приложения, аналитика или централизованная recovery-логика. |
Почему сервис загрузки remote не должен знать бизнес-логику приложения?
|
Loader отвечает за разрешение модуля, создание компонента и технический lifecycle. Решения о фильмах, бронировании и доступности принадлежат host orchestration или domain services, иначе loader нельзя переиспользовать. |
SSR и hydration
Middle+ or Senior #
Могут ли remote-приложения быть SSR?
|
Да, но server renderer должен уметь разрешить remote, загрузить совместимый server bundle и согласовать HTML с последующей hydration. Это заметно сложнее browser-only композиции. |
Какие дополнительные сложности появляются при SSR и micro frontends?
|
Нужно согласовать server и browser entries, сетевую доступность remote с сервера, shared dependencies, latency, кеширование, ошибки частичного render и детерминированный HTML для hydration. |
Почему при SSR возникает ошибка window is not defined?
|
Server runtime не предоставляет browser global |
Почему при SSR возникает ошибка document is not defined?
|
Node server не имеет browser DOM |
Почему ngOnInit не всегда подходит для загрузки remote widgets?
|
|
Когда использовать afterNextRender()?
|
Когда интеграция требует созданного DOM, browser APIs или доступного |
Почему remote widgets часто монтируют только на клиенте, даже если shell поддерживает SSR?
|
Так shell сохраняет SEO и быстрый initial HTML, а remote integration избегает server federation, browser globals и hydration mismatch. Цена — placeholder до client mount и более поздняя готовность виджета. |
Как сделать SSR-safe код в Angular?
|
Не обращаться к browser globals на уровне модуля, использовать platform-neutral APIs, изолировать browser services и выполнять DOM-интеграции в render callbacks или после явной проверки платформы. |
Что такое BootstrapContext в server bootstrap?
|
|
Почему bootstrapApplication на сервере требует BootstrapContext?
|
Server renderer создает контекст для запроса и ожидает, что bootstrap использует его. Без контекста приложение может создать неподходящую platform instance или потерять request-scoped providers. |
Чем main.ts отличается от main.server.ts?
|
Browser entry инициализирует приложение в DOM и может настраивать client federation. Server entry экспортирует bootstrap
для renderer, принимает |
Почему manifest может открываться в браузере, но не загружаться во время SSR?
|
URL |
Что такое hydration mismatch и как микрофронтенды могут его спровоцировать?
|
Mismatch возникает, когда client ожидает DOM, отличный от server HTML. Remote может изменить разметку до hydration, отрендерить разные данные или создать browser-only элементы в server-rendered области. |
Deployment, versioning и rollback
Middle+ or Senior #
Как деплоить host и remote-приложения независимо?
|
У каждого приложения должен быть отдельный build и release pipeline. Remote сначала публикует versioned assets, затем контролируемо обновляется manifest; host выпускается отдельно и сохраняет совместимость с доступными версиями remote. |
Какие артефакты деплоит remote-приложение?
|
|
Где должен лежать remoteEntry.json после деплоя?
|
По стабильному HTTPS URL, доступному host и разрешенному security policy. Часто это CDN path, связанный с приложением
или версией, например |
Где хранить manifest для dev/stage/prod?
|
В environment-specific конфигурации или config service, управляемом deployment pipeline. Не следует вручную менять production manifest без истории, валидации и возможности быстрого rollback. |
Как host узнает URL нового remote-приложения?
|
Из manifest, который загружается при старте или встраивается для конкретного окружения. Обновление mapping переключает host на новый remote без изменения его application code. |
Что будет, если host старый, а remote новый?
|
Все продолжит работать только при backward-compatible remote contract. Удаленный export, переименованный input или измененная payload schema приведут к runtime-ошибке старого host. |
Что будет, если remote старый, а host новый?
|
Новый host может запросить отсутствующий export или передать неподдерживаемые данные. Поэтому host должен либо поддерживать старый контракт, либо проверять capability/version до использования новой функции. |
Как версионировать контракты между host и remote?
|
Версионируют exposed modules, TypeScript/schema package или capability metadata по SemVer. Breaking change получает новую major-версию или новый параллельный contract identifier. |
Как организовать backward compatibility между host и remote?
|
Сначала remote добавляет новый API, сохраняя старый, затем обновляются consumers, и только после измеренного перехода удаляется legacy contract. Полезны defaults, optional fields и tolerant readers. |
Как безопасно изменить exposedModule или exportName?
|
Временно публиковать старое и новое имя, обновить host, проверить production usage и только затем удалить alias. Изменение должно проходить contract и integration tests. |
Почему нельзя бездумно переименовывать exposed module?
|
Его имя — часть runtime API, записанная в host configuration. В отличие от внутреннего refactoring, компилятор remote не найдет внешних consumers и не предупредит об их поломке. |
Как организовать rollback remote-приложения?
|
Хранить предыдущие immutable releases и атомарно вернуть manifest mapping на проверенный |
Как организовать rollback host-приложения?
|
Повторно активировать предыдущий host release и соответствующую конфигурацию manifest. Rollback должен учитывать, что remote уже могли перейти вперед, поэтому их контракты обязаны быть backward-compatible. |
Какие риски есть у кеширования remoteEntry.json?
|
Устаревший entry может ссылаться на удаленные chunks или старый контракт. Смешивание entry одного release с assets другого вызывает ошибки импорта, которые трудно воспроизвести локально. |
Нужно ли кешировать federation manifest?
|
Да, но обычно с коротким TTL, revalidation или управляемым versioned URL. Стратегия зависит от того, насколько быстро нужно переключать remote и отключать аварийный release. |
Почему remoteEntry.json часто кешируют осторожнее, чем JS chunks?
|
Entry является изменяемой картой текущего release, а content-hashed chunks immutable. Chunks можно кешировать надолго, тогда как entry должен достаточно быстро указывать на актуальный набор файлов. |
Как CDN влияет на деплой микрофронтендов?
|
CDN снижает latency и распределяет assets, но добавляет cache keys, propagation delay, CORS/CSP настройки и invalidation. Release должен учитывать согласованность entry и chunks во всех edge locations. |
Как CDN cache может сломать загрузку remote?
|
Очистка устаревшего entry может быстро переключить клиентов на исправление. Но удаление старых chunks или несогласованная invalidation оставит открытые сессии с entry, ссылки которого больше не работают. |
Что такое canary deployment для remote-приложения?
|
Это направление небольшой доли пользователей или внутренних сотрудников на новую версию remote. Manifest или edge routing выбирает версию, а метрики сравниваются до полного rollout. |
Как feature flags помогают деплоить микрофронтенды?
|
Flag может включить новый remote, contract path или функцию для выбранной аудитории без повторной сборки. Нужны предсказуемый fallback, владелец flag и удаление завершенных флагов. |
Как откатить сломанный remote без деплоя host?
|
Изменить управляемый manifest/config или remote feature flag так, чтобы host не монтировал виджет либо использовал резервную версию. Host должен заранее поддерживать отсутствие optional remote. |
Что должен показывать host, если remote не загрузился после деплоя?
|
Локальный доступный fallback с понятным сообщением и retry, если повтор может помочь. Критический remote может переводить весь сценарий в error state, но не должен оставлять пустой экран без объяснения. |
Какие метрики и алерты нужны для микрофронтендов в production?
|
Успешность и latency загрузки entry/chunks, mount time, ошибки по remote/version, fallback rate, contract errors и влияние на Core Web Vitals. Алерт должен указывать конкретный remote и release. |
Как логировать ошибки загрузки remote-приложений?
|
Добавлять remote name, entry URL, exposed module, host/remote versions, environment, этап загрузки и correlation ID. Секреты и персональные payloads в client logs отправлять нельзя. |
Как проверять совместимость host и remote в CI?
|
Собирать каждый remote, поднимать его artifacts и запускать contract/integration tests поддерживаемых host versions. Также проверять shared dependency ranges и наличие всех exposed exports. |
Какие contract tests нужны для host и remote?
|
Это автоматическая проверка публичного соглашения между producer remote и consumer host: имен exports, inputs, outputs, payload schemas и обязательного поведения без полного E2E всех реализаций. |
Какие e2e-сценарии нужны перед выкладкой host и remotes?
|
Загрузка каждого remote, основной cross-remote flow, partial failure, retry, старая/новая совместимая версия, navigation, auth и rollback configuration. Проверяют также отсутствие блокировки host при optional remote failure. |
CSS, UI и Design System
Middle+ or Senior #
Кто должен отвечать за layout: host или remote?
|
Host отвечает за page layout, размеры и расположение slots. Remote отвечает за содержимое внутри выделенной области и должен корректно работать в явно документированных responsive constraints. |
Кто должен отвечать за внутренние стили виджета: host или remote?
|
Remote владеет своей внутренней разметкой и component styles. Host может передавать semantic design tokens и параметры контейнера, но не должен зависеть от внутренних selectors remote. |
Почему host не должен глубоко стилизовать внутренности remote?
|
Внутренний DOM не является публичным контрактом и может измениться при независимом release. Deep selectors создают скрытую связанность и ломают encapsulation, тестирование и безопасный rollout. |
Какие проблемы со стилями бывают в микрофронтендах?
|
Конфликты global selectors, разный reset, несовместимые tokens, дубли fonts/styles, различия responsive behavior и z-index систем. Виджеты также могут менять layout после поздней загрузки. |
Как избежать конфликта глобальных CSS-стилей между remote-приложениями?
|
Минимизировать globals, использовать Angular style encapsulation, scoped naming и согласованный reset в host. Общие tokens публиковать через CSS custom properties, а не через selectors внутренних элементов. |
Как микрофронтенды могут использовать общую design system?
|
Через versioned package компонентов и semantic tokens с документированным compatibility range. Angular package часто настраивают как shared dependency, если все remote способны использовать совместимую runtime-версию. |
Какие риски есть у разных версий design system в разных remote?
|
Визуальная несогласованность, разные accessibility fixes, duplicated code и конфликт global assets. При singleton sharing несовместимые версии могут также привести к runtime-ошибке вместо изолированной копии. |
Testing и security
Middle+ or Senior #
Как тестировать remote-приложение отдельно?
|
Проверять компоненты и domain logic unit/integration-тестами, а exposed contract — через standalone harness или test host. Remote также должен собираться и запускаться независимо от production host. |
Как тестировать host без реальных remote?
|
Подменить abstraction загрузчика и вернуть локальные test components с теми же inputs/outputs. Так host orchestration и fallback states тестируются детерминированно без сети и federation runtime. |
Как мокать remote widgets в тестах host-приложения?
|
Создать минимальные standalone components, реализующие нужный публичный контракт, и настроить loader stub возвращать их
|
Как проверить fallback UI, если remote недоступен?
|
Настроить loader mock на rejected promise или |
Как тестировать контракты между host и remote?
|
Проверять наличие exposed export, совместимость input/output payloads и ожидаемую реакцию на события. Эти тесты запускают как в producer pipeline, так и на матрице поддерживаемых consumer versions. |
Какие security-риски появляются при runtime-загрузке remote-кода?
|
Host исполняет JavaScript с правами своего origin: remote может читать доступные данные, менять DOM и выполнять запросы. Компрометация remote pipeline или CDN становится компрометацией host session. |
Почему host должен доверять только известным remoteEntry URL?
|
URL определяет исполняемый код. Разрешение произвольного адреса из query params или пользовательского ввода превращает federation loader в механизм удаленного выполнения недоверенного JavaScript. |
Что может пойти не так, если manifest можно изменить без контроля?
|
Злоумышленник или ошибочная автоматизация может перенаправить host на вредоносный или несовместимый remote. Нужны ограниченный доступ, audit log, validation, approvals и rollback. |
Как CSP влияет на загрузку remote-приложений?
|
|
Что такое supply chain risk в микрофронтендах?
|
Это риск компрометации dependency, build pipeline, registry, artifact storage или CDN одного remote. Из-за композиции во время выполнения вредоносный release попадает в host без изменения его репозитория. |
Как ограничить влияние сломанного или небезопасного remote?
|
Использовать allowlist URL, CSP, независимые permissions, минимальные публичные данные, мониторинг и аварийное отключение. Для недоверенного кода нужна более сильная изоляция, например iframe с sandbox, а не обычный Angular component. |
Tooling #
Feature toggles в Angular часто реализуют через service, guard, directive или provider. Общие типы флагов, lifecycle, риски и fallback-стратегии описаны в разделе Feature toggles.
Junior #
Что такое TypeScript program?
|
|
Зачем нужен tsconfig.app.json?
|
Он задает compiler options и roots именно application build, отделяя их от tests, tools и base |
Что такое Angular builder?
|
Builder — реализация target вроде |
Middle #
Какие frontend guidelines особенно важны для Angular-проекта?
|
Для Angular-проекта важны соглашения о структуре standalone components, signals и RxJS, smart/presentational components, forms, HTTP services, error handling, lazy loading, testing и naming. Без таких правил разные части приложения начинают выглядеть как разные frameworks внутри одного репозитория. |
Почему Angular compiler требует, чтобы файл с @Component входил в TypeScript compilation?
|
Angular анализирует component metadata в рамках TypeScript program. Если файл не является root и не достижим через imports, compiler не создаст для него Angular definitions. Физического наличия файла в directory недостаточно. |
Чем files отличается от include в tsconfig?
|
|
Почему файл может физически существовать, но не входить в TypeScript compilation?
|
Он может не совпадать с |
Что такое Vite dev server в Angular?
|
Современный Angular development server использует Vite для быстрой раздачи и обновления приложения, оставаясь под
управлением Angular builder. Angular CLI настраивает compilation, assets и framework integration. Это не означает, что
проект обязан иметь ручной |
Middle+ or Senior #
Что стоит фиксировать в Angular coding guidelines?
|
Стоит фиксировать структуру feature folders, правила для components, services, directives и pipes, подход к state management, forms, error handling, loading states и тестированию. Также полезно описать, когда использовать signals, когда RxJS, а когда обычные class fields или pure functions. |
Frontend topics в Angular #
Junior #
Что такое esbuild?
|
esbuild — быстрый bundler и transformer на Go. Angular application builder использует его как часть build pipeline для bundling и оптимизаций вместе с Angular compiler. Он не заменяет template type checking. |
Middle #
Как тестировать Angular-компонент с async data fetching?
|
Проверяют не внутренний вызов метода, а observable behavior: loading state, успешный render, empty state, error state и отмену устаревшего запроса, если она является частью контракта. Подходы:
Тест должен управлять временем и данными явно, а не ждать произвольные delays. |
Требования к написанию кода на TypeScript
|
На самом деле требования бывают разные и зависят от команды к команде. Самые эффективные для себя считаю использование модификаторов доступа и принудительного указания типов данных для всех переменных, методов и членов класса, которые вы используете в коде. Желательно все необходимые правила конвенции кода настраивать в ESLint.
|
Зачем нужен ESLint (TSLint) и Prettier?
|
ESLint анализирует код и находит потенциальные ошибки, небезопасные конструкции и нарушения соглашений. С TypeScript он работает через typescript-eslint, а Angular-правила предоставляет angular-eslint. Prettier отвечает за форматирование: отступы, переносы, кавычки и другие визуальные правила. Он не заменяет семантический анализ ESLint. TSLint устарел и больше не развивается; современные TypeScript-проекты используют ESLint. Обычная схема:
Цель инструментов — быстрый автоматический feedback и единый стиль, а не максимальное количество строгих правил. Правило должно предотвращать реальную проблему или поддерживать договоренность команды. |
Middle+ or Senior #
Как объяснить Angular PWA cache strategies на интервью?
|
Нужно разделить app shell, static assets и data requests. App shell и versioned assets можно кешировать агрессивнее, потому что их имена меняются при build. API data требует отдельной стратегии: freshness, performance, timeout, maxAge, fallback и правила инвалидирования. В Angular Service Worker конфигурация описывает asset groups и data groups. Хороший ответ упоминает update flow, offline fallback, риски stale data и то, что Service Worker не заменяет backend authorization.
|
Что такое SSR entry?
|
Это server-side entry, из которого builder создает bundle для обработки HTTP requests или prerender. Он подключает server providers и экспортирует bootstrap/handler, а не монтирует приложение в browser DOM. Конкретное имя задается workspace configuration. |
Практика по Angular frontend tasks #
Middle+ or Senior #
Практическая задача: перенесите autocomplete в Angular.
|
Что проверяет: typed forms, RxJS cancellation, состояния загрузки, accessibility. В Angular autocomplete обычно раскладывают на typed form/control state, поток поиска, отмену запросов и доступный UI.
Для async query хорошо подходят RxJS operators:
Компонент должен явно иметь состояния |