Справочник по Angular и React · модуль 0 · фронтенд в эпоху ИИ
0.1
Фронтенд
и фреймворки
В этой главе разобрано, что такое фронтенд и какую работу он выполняет в приложении. По годам показано, как веб-страница превратилась в приложение и почему появились фреймворки. Центральная часть главы — задача синхронизации состояния и интерфейса: она показана на работающей витрине магазина, эту задачу решают и React, и Angular.
- Категория
- Основы
- Уровень
- Вводный
- Что нужно знать
- HTML, CSS и основы JavaScript: переменная, функция, обработчик события
- Зачем это знать
- Понимать, какую задачу решает фреймворк, прежде чем учить его синтаксис
§1Фронтенд и бэкенд
В ресторане есть зал и кухня. Гость видит зал: меню, стол, официанта, счёт. Кухня от гостя скрыта: там хранятся продукты и готовятся блюда. Зал отвечает за то, как гость делает заказ и что он при этом видит; кухня — за то, чтобы заказ был выполнен правильно.
Зал ресторана не может готовить сам, а фронтенд может часть работы выполнять без сервера: считать сумму, проверять форму, хранить черновик.
Веб-приложение делится на две части по месту, где выполняется код. Фронтенд — часть приложения, которая работает в браузере пользователя: она показывает интерфейс, принимает нажатия и ввод с клавиатуры и отправляет запросы на сервер. Бэкенд — часть, которая работает на сервере: хранит данные в базе, проверяет права, считает деньги и отвечает на запросы фронтенда. В сравнении с рестораном фронтенд — это зал, бэкенд — кухня.
Фронтенд строится из трёх технологий, которые браузер исполняет без дополнительных программ. HTML описывает структуру страницы: заголовки, списки, кнопки, поля ввода. CSS задаёт внешний вид: цвета, шрифты, расположение блоков. JavaScript описывает поведение: что происходит при нажатии, как меняется страница, когда пришли данные. React и Angular написаны на JavaScript и в итоге тоже выдают браузеру HTML, CSS и JavaScript — других языков браузер не исполняет.
Где выполняется код приложения
Код фронтенда скачивается в браузер и выполняется на компьютере пользователя. Поэтому его может прочитать любой, кто открыл страницу: пароли и ключи доступа в нём хранить нельзя.
Из того, что код фронтенда выполняется у пользователя, следует ограничение. Всё, что попало во фронтенд, видно в инструментах разработчика браузера: код, адреса запросов, данные ответов. Проверка «есть ли у пользователя право удалить заказ» обязана выполняться на сервере, даже если кнопка «Удалить» на странице скрыта. Фронтенд отвечает за удобство и понятность, сервер — за правила и сохранность данных.
Следующий раздел показывает, как роль фронтенда менялась начиная с 1995 года.
§2От страницы к приложению
Первые сайты были документами: сервер присылал готовую страницу, пользователь читал её и нажимал ссылку, после чего сервер присылал следующую страницу целиком. JavaScript, появившийся в 1995 году, сначала использовали для мелочей: проверить поле формы, показать подсказку. Перелом произошёл, когда страница научилась получать данные с сервера, не перезагружаясь. В 2004 году Google выпустил почту Gmail, где письма открывались без перезагрузки страницы, а в 2005 году этот подход получил название Ajax.
С этого момента на странице появилось то, что раньше было только у программ на компьютере: данные, которые меняются, пока пользователь работает. Чем больше таких данных, тем сложнее следить, чтобы все части страницы показывали одно и то же. Фреймворки появились как ответ на эту сложность. Лента ниже показывает основные даты; синие отметки относятся к React, малиновые — к Angular, чёрные — к инструментам ИИ.
- 1995JavaScript появляется в браузере Netscape Navigator. Язык написан Бренданом Айком за десять дней.
- 2004Gmail: письма открываются без перезагрузки страницы. В 2005 году подход называют Ajax.
- 2006jQuery — библиотека, которая упростила поиск элементов на странице и их изменение. Подход остаётся ручным: разработчик сам решает, какой элемент и когда поменять.
- 2010AngularJS от Google: шаблон связывается с данными, и при изменении данных страница обновляется сама.
- 2013React от Facebook (сейчас Meta): интерфейс описывается как функция от данных и собирается из компонентов.
- 2016Angular 2: фреймворк переписан с нуля на TypeScript. С этой версии название пишется без «JS»; AngularJS и Angular — разные продукты.
- 2019Хуки в React 16.8: состояние и эффекты описываются в обычных функциях. Так React пишут сейчас.
- 2023Сигналы в Angular 16: новый способ хранить состояние, после которого Angular сблизился с React по модели работы.
- 2025Вайбкодинг: Андрей Карпаты называет так работу, при которой код целиком пишет ИИ по описанию. Этому посвящена глава 0.3.
- 2026React Foundation: Meta передаёт React в Linux Foundation (24 февраля). Angular 22 (3 июня) делает стабильными Signal Forms и инструменты для ИИ-агентов.
В ленте видно, что React и Angular появились почти одновременно и решали одну задачу: как сделать, чтобы страница с меняющимися данными оставалась согласованной. За пятнадцать лет оба прошли через крупные переделки, и в 2026 году оба развиваются. Задача, ради которой они созданы, разобрана в следующем разделе на примере.
§3Состояние и интерфейс
Табло вылетов в аэропорту можно обновлять двумя способами. Первый: дежурный, узнав о задержке рейса, идёт к табло и переставляет буквы в строке рейса, затем к табло у выхода на посадку, затем к табло у стойки регистрации. Если он забыл одно табло, пассажиры видят разное время. Второй способ: есть одно расписание, и все табло перерисовываются из него. Дежурный меняет только расписание.
Табло перерисовываются целиком, а фреймворк меняет на странице только изменившиеся элементы, иначе страница работала бы медленно.
Состояние — данные, которые описывают, что сейчас происходит в интерфейсе: какие товары в корзине, какой пункт меню открыт, что введено в поле поиска. В сравнении с аэропортом состояние — это расписание. Интерфейс — то, что пользователь видит на экране; в сравнении это табло. Задача фронтенда — чтобы интерфейс всегда соответствовал состоянию, сколько бы мест на экране ни показывали одни и те же данные.
Демонстрация: ручное обновление и обновление из состояния
Ниже две одинаковые витрины. Число товаров в корзине показано в трёх местах: значок в шапке, подпись на кнопке и строка «Итого». Цена показана в двух: в строке товара и в «Итого». В левой витрине каждое место обновляет отдельная строка кода — так писали с jQuery. В правой есть одна переменная состояния и одна функция, которая рисует витрину из неё. Под каждой витриной журнал показывает, какие изменения страницы выполнил код.
Нажмите «В корзину» два раза, затем «Скидка 10%» в обеих витринах. Слева обработчик скидки обновил строку «Итого», а в строке товара осталась старая цена 450 ₽: второе место, где показана цена, в обработчике не учтено. Справа обработчик меняет только состояние, а витрина перерисовывается целиком из него.
В левой витрине ошибка устроена так же, как в настоящих проектах. Пока событий два — «добавить» и «скидка» — и мест на экране три, разработчик помнит, что где обновлять. Когда событий двадцать, а мест, где показана корзина, десять (шапка, боковая панель, страница оформления, всплывающее окно), число связей «событие → место» растёт как произведение: двести строк, каждую из которых нужно не забыть. Код слева выглядит так:
let count = 0; let price = 450; addButton.onclick = () => { count = count + 1; badge.textContent = count; // место 1 buttonCounter.textContent = count; // место 2 total.textContent = `Итого: ${count} шт. · ${count * price} ₽`; // место 3 }; saleButton.onclick = () => { price = 405; total.textContent = `Итого: ${count} шт. · ${count * price} ₽`; // пропущено: priceLabel.textContent = `${price} ₽`; — место 4, цена у товара };
Справа код разделён на две части. Первая — функция render: она получает состояние и выставляет по нему все четыре места. Вторая — обработчики событий: они меняют только состояние и вызывают render. В обработчике скидки нет ни одного места экрана, поэтому пропустить место в нём нельзя: все места перечислены один раз, в render.
const state = { count: 0, price: 450 }; function render(state) { badge.textContent = state.count; buttonCounter.textContent = state.count; priceLabel.textContent = `${state.price} ₽`; total.textContent = `Итого: ${state.count} шт. · ${state.count * state.price} ₽`; } addButton.onclick = () => { state.count += 1; render(state); }; saleButton.onclick = () => { state.price = 405; render(state); };
Этот приём записывают формулой UI = f(state): интерфейс есть функция от состояния. Разработчик описывает, как должен выглядеть экран при любом состоянии; шаги перехода от одного вида к другому выполняет код фреймворка. Такой способ называют декларативным: описывается результат. Способ слева называют императивным: описываются шаги.
У функции render из примера есть недостаток: она переписывает все три места при каждом нажатии, даже если поменялось одно. На витрине из трёх строк это незаметно, а на странице с таблицей из тысячи строк полная перерисовка займёт заметное время. Поэтому фреймворк выполняет ещё одну работу: сравнивает новое описание экрана с предыдущим и меняет в браузере только те элементы, которые отличаются. React для этого сравнивает два дерева описаний элементов, Angular с сигналами отслеживает, какие места страницы зависят от какого значения. Способы разные, результат одинаковый: разработчик пишет как в правой витрине, а страница обновляется так же экономно, как в левой.
Одна функция render на всю страницу быстро становится слишком большой. Следующий шаг — разделить страницу на части, у каждой из которых своё описание и своё состояние.
§4Компоненты
Кухонный гарнитур собирают из модулей: шкаф под мойку, шкаф с ящиками, навесной шкаф. Каждый модуль изготовлен по своему чертежу, а один и тот же модуль можно поставить несколько раз. Чтобы заменить ящик, не нужно разбирать весь гарнитур.
Модули мебели не передают друг другу ничего, а компоненты получают данные от родителя и сообщают ему о событиях.
Компонент — часть интерфейса, у которой есть своё описание вида, своё поведение и, при необходимости, своё состояние. Кнопка, карточка товара, шапка сайта, вся страница каталога — всё это компоненты. Компонент можно использовать несколько раз: карточка товара одна, а на странице каталога их двадцать, у каждой свои данные.
Компоненты вкладываются друг в друга и образуют дерево. В корне — приложение целиком, в нём — шапка, каталог и корзина, в каталоге — карточки товаров. Данные идут по дереву сверху вниз: каталог передаёт каждой карточке её товар. События идут снизу вверх: карточка сообщает наверх, что на ней нажали «В корзину», и состояние корзины меняется в общем родителе.
Дерево компонентов страницы магазина
Голубым отмечены компоненты, которые показывают корзину. Состояние корзины хранится в общем родителе App, оба компонента получают его сверху. Когда карточка сообщает о покупке, App меняет состояние, и обе голубые части перерисовываются. Это та же модель, что в правой витрине из §3, разложенная по частям.
В React и в Angular компонент устроен по-разному, но содержит одни и те же части: описание того, как он выглядит, данные, которые он получает от родителя, и собственное состояние. Ниже один и тот же компонент — значок корзины из дерева — записан двумя способами. Переключатель в шапке страницы выбирает фреймворк; выбор запоминается и действует на всю книгу.
type Props = { count: number }; export function CartBadge({ count }: Props) { return <span className="badge">{count}</span>; }
import { Component, input } from '@angular/core'; @Component({ selector: 'app-cart-badge', template: `<span class="badge">{{ count() }}</span>`, }) export class CartBadge { count = input.required<number>(); }
В React компонент — функция. Она получает данные от родителя в объекте props (здесь из него сразу взято поле count) и возвращает описание разметки. Запись <span>{count}</span> внутри JavaScript называется JSX: это разметка, в которую в фигурных скобках подставляются значения. Тип Props написан на TypeScript и указывает, что count — число.
В Angular компонент — класс с декоратором @Component. В декораторе указаны имя тега, под которым компонент вставляется в разметку родителя (app-cart-badge), и шаблон. Данные от родителя объявлены полем count через функцию input; в шаблоне значение читается вызовом count(), потому что input возвращает сигнал — обёртку, по которой Angular отслеживает изменения.
В обеих записях компонент получает число от родителя и показывает его; различается только синтаксис. Компоненты React подробно разбираются в модуле 1, запись на Angular — в обзорной паре модуля 4.
Компоненты и обновление из состояния — ядро обоих фреймворков. Вокруг ядра есть ещё несколько задач, которые в любом приложении решаются одинаково часто.
§5Что берёт на себя фреймворк
Кроме отрисовки из состояния, приложению нужны ещё пять вещей. Переход между страницами без перезагрузки — маршрутизация: адрес в строке браузера меняется, сервер новую страницу не присылает, а фронтенд показывает другой компонент. Запросы к серверу и показ состояния загрузки. Формы с проверкой ввода. Общие данные, которые нужны многим компонентам сразу, например вошедший пользователь. И сборка — превращение исходного кода на TypeScript в файлы, которые исполняет браузер.
React и Angular по-разному отвечают на вопрос, кто решает эти задачи. Angular включает решения для всех пяти в сам фреймворк: маршрутизатор, клиент HTTP, формы, внедрение зависимостей и сборку выпускает одна команда в Google, и они согласованы между собой. React отвечает только за отрисовку и компоненты, а маршрутизацию, запросы и формы берут из отдельных библиотек или из надстроек вроде Next.js. Поэтому React называют библиотекой, а Angular — платформой. Что из этого следует для проекта и для разработчика, разобрано в главе 0.2.
| Задача | React | Angular |
|---|---|---|
| Компоненты и отрисовка из состояния | сам React | сам Angular |
| Переходы между страницами | отдельная библиотека: React Router или надстройка Next.js | встроенный @angular/router |
| Запросы к серверу | fetch браузера или библиотеки, например TanStack Query | встроенный HttpClient |
| Формы и проверка ввода | библиотеки, например React Hook Form | встроенные формы, с версии 22 — Signal Forms |
| Сборка проекта | Vite или сборщик надстройки | Angular CLI: команда ng |
Таблица показывает основную разницу, с которой студент сталкивается в первый же день. В проекте на Angular состав инструментов одинаков почти везде, и, перейдя в другую команду, разработчик узнаёт знакомую структуру папок. В проекте на React набор библиотек выбирает команда, и два проекта на React могут отличаться сильнее, чем проект на React и проект на Vue.
§6Проверьте себя
Кнопка «Удалить заказ» скрыта у пользователей без прав. Достаточно ли этого, чтобы они не могли удалить заказ?
Нет. Код фронтенда выполняется в браузере пользователя, и запрос на удаление можно отправить без кнопки — из инструментов разработчика или любой программой. Право на удаление проверяет сервер при каждом запросе. Скрытая кнопка относится к удобству интерфейса; защитой она не является.
Что такое состояние интерфейса? Приведите три примера для страницы интернет-магазина.
Состояние — данные, по которым видно, что сейчас происходит в интерфейсе. Примеры: список товаров в корзине, текст в поле поиска, открыт ли фильтр «Цена», номер страницы каталога, идёт ли сейчас загрузка.
Почему ошибка в левой витрине из §3 появилась в обработчике скидки?
При ручном обновлении каждый обработчик должен помнить все места экрана, которые зависят от изменённых данных. Обработчик скидки менял цену, а цена показана в двух местах; он обновил «Итого» и пропустил строку товара. Чем больше событий и мест, тем больше таких связей, и каждую можно пропустить. В правой витрине обработчик меняет только данные, а места обновляет одна функция.
Что означает запись UI = f(state)?
Интерфейс вычисляется из состояния: при одном и том же состоянии экран выглядит одинаково. Разработчик описывает, как выглядит экран при любом состоянии, а фреймворк приводит страницу в браузере к этому описанию.
Чем React как библиотека отличается от Angular как платформы с точки зрения нового проекта?
В Angular маршрутизация, запросы, формы и сборка входят в сам фреймворк, и проекты устроены похоже. В React фреймворк отвечает за компоненты и отрисовку, а остальные задачи решаются библиотеками, которые команда выбирает сама. Поэтому в начале проекта на React нужно принять больше решений.
Итог главы
Фронтенд — часть приложения, которая выполняется в браузере пользователя и отвечает за интерфейс; правила и данные остаются на сервере. С появлением Ajax на странице появилось меняющееся состояние, и задача держать интерфейс согласованным с ним стала основной. React и Angular решают её одинаково по смыслу: интерфейс описывается как функция от состояния и собирается из компонентов, а фреймворк обновляет в браузере только изменившиеся места. Различаются они тем, сколько задач кроме отрисовки фреймворк берёт на себя.
Источники
- react.dev — Thinking in React
- angular.dev — Components
- angular.dev — Signals
- React Blog — React v16.8: The One With Hooks (6 февраля 2019)
- Linux Foundation — Announces the Formation of the React Foundation (24 февраля 2026)
- Ninja Squad — What's new in Angular 22.0 (3 июня 2026)