03 — Bootstrap: как приложение запускается
Цель: понять, что происходит между «браузер скачал main.js» и «на экране появился
счётчик: 0».
Точка входа
В main.ts одна строчка:
bootstrapApplication(App);
bootstrap = «запустить с нуля» (как «завести машину»). Эта функция и раскручивает
всё приложение.
Что происходит по шагам
1. index.html в браузере: <body><app-root></app-root></body> ← пустое место
2. main.js выполняется → bootstrapApplication(App)
3. создаются инжекторы (склад зависимостей)
4. запускаются инициализаторы (если есть)
5. Angular ищет <app-root> на странице ← единственный реальный поиск в DOM!
6. создаёт экземпляр класса App (через DI)
7. вызывает template-функцию в режиме СОЗДАТЬ (rf & 1)
8. внутри <app-root> появляются <h1>, <p>Счётчик: 0</p>, кнопка...
Разберём непонятные места.
Шаг 3 — «инжекторы» простыми словами
Инжектор — это склад готовых объектов (сервисов). Когда твоему компоненту нужен,
скажем, HttpClient, он не создаёт его сам — просит у склада: «дай мне HttpClient».
Склад либо выдаёт уже готовый, либо создаёт и запоминает.
Зачем: один и тот же сервис переиспользуется везде (не плодим копии), и его легко подменить (например, в тестах). Это и есть DI — Dependency Injection, «впрыск зависимостей».
При старте создаётся два уровня склада:
- корневой (на всё приложение) — туда кладутся
provide...()из bootstrap; - окружение — служебные вещи рантайма.
Шаг 5 — единственный настоящий поиск в DOM
Вот это важно и часто путают: Angular ищет элемент в живой странице ровно один
раз — когда находит <app-root> для корневого компонента (по его selector).
Всё остальное (где какой дочерний компонент, какая директива) определяется не поиском в DOM, а заранее — на компиляции. Подробно про это → 07 — Селекторы.
Шаг 7 — первый рендер (режим «создать»)
Помнишь два режима template-функции из главы 01? При старте
вызывается режим create (rf & 1):
<app-root>
├─ <h1>demo21</h1> ← создан
├─ <p>Счётчик: 0</p> ← создан, число = 0 (начальное)
├─ <p>Удвоенный: 0</p> ← создан
├─ <button>+1</button> ← создан + повешен (click)
├─ (@if: count > 2? нет → блок НЕ создан)
└─ <ul></ul> ← пустой (@for: items() = [], 0 элементов)
Так как count = 0:
@if (count() > 2)ложно → блок «Больше двух!» не создаётся вообще;@for (n of items())—items()пустой массив → ноль<li>.
После этого один раз срабатывают хуки «после первого рендера» (afterNextRender).
Что в итоге на экране
demo21
Счётчик: 0
Удвоенный: 0
[ +1 ]
Приложение запущено, DOM построен. Дальше оно просто ждёт, пока ты что-нибудь нажмёшь. Что произойдёт при клике — в следующей главе.
Дальше → 04 — Runtime и change detection.