Модуль 0 · Фронтенд в эпоху ИИ

Справочник по Angular и React · модуль 0 · фронтенд в эпоху ИИ

0.1

0.1

Фронтенд
и фреймворки

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

Категория
Основы
Уровень
Вводный
Что нужно знать
HTML, CSS и основы JavaScript: переменная, функция, обработчик события
Зачем это знать
Понимать, какую задачу решает фреймворк, прежде чем учить его синтаксис

§1Фронтенд и бэкенд

Сравнение из жизни

В ресторане есть зал и кухня. Гость видит зал: меню, стол, официанта, счёт. Кухня от гостя скрыта: там хранятся продукты и готовятся блюда. Зал отвечает за то, как гость делает заказ и что он при этом видит; кухня — за то, чтобы заказ был выполнен правильно.

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

Веб-приложение делится на две части по месту, где выполняется код. Фронтенд — часть приложения, которая работает в браузере пользователя: она показывает интерфейс, принимает нажатия и ввод с клавиатуры и отправляет запросы на сервер. Бэкенд — часть, которая работает на сервере: хранит данные в базе, проверяет права, считает деньги и отвечает на запросы фронтенда. В сравнении с рестораном фронтенд — это зал, бэкенд — кухня.

Фронтенд строится из трёх технологий, которые браузер исполняет без дополнительных программ. HTML описывает структуру страницы: заголовки, списки, кнопки, поля ввода. CSS задаёт внешний вид: цвета, шрифты, расположение блоков. JavaScript описывает поведение: что происходит при нажатии, как меняется страница, когда пришли данные. React и Angular написаны на JavaScript и в итоге тоже выдают браузеру HTML, CSS и JavaScript — других языков браузер не исполняет.

Где выполняется код приложения

Браузер пользователя — фронтенд HTML CSS JavaScript структура · вид · поведение React и Angular работают здесь запрос ответ Сервер — бэкенд код сервера база данных права · деньги · хранение пользователь этот код не видит

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

Из того, что код фронтенда выполняется у пользователя, следует ограничение. Всё, что попало во фронтенд, видно в инструментах разработчика браузера: код, адреса запросов, данные ответов. Проверка «есть ли у пользователя право удалить заказ» обязана выполняться на сервере, даже если кнопка «Удалить» на странице скрыта. Фронтенд отвечает за удобство и понятность, сервер — за правила и сохранность данных.

Следующий раздел показывает, как роль фронтенда менялась начиная с 1995 года.

§2От страницы к приложению

Первые сайты были документами: сервер присылал готовую страницу, пользователь читал её и нажимал ссылку, после чего сервер присылал следующую страницу целиком. JavaScript, появившийся в 1995 году, сначала использовали для мелочей: проверить поле формы, показать подсказку. Перелом произошёл, когда страница научилась получать данные с сервера, не перезагружаясь. В 2004 году Google выпустил почту Gmail, где письма открывались без перезагрузки страницы, а в 2005 году этот подход получил название Ajax.

С этого момента на странице появилось то, что раньше было только у программ на компьютере: данные, которые меняются, пока пользователь работает. Чем больше таких данных, тем сложнее следить, чтобы все части страницы показывали одно и то же. Фреймворки появились как ответ на эту сложность. Лента ниже показывает основные даты; синие отметки относятся к React, малиновые — к Angular, чёрные — к инструментам ИИ.

  1. 1995JavaScript появляется в браузере Netscape Navigator. Язык написан Бренданом Айком за десять дней.
  2. 2004Gmail: письма открываются без перезагрузки страницы. В 2005 году подход называют Ajax.
  3. 2006jQuery — библиотека, которая упростила поиск элементов на странице и их изменение. Подход остаётся ручным: разработчик сам решает, какой элемент и когда поменять.
  4. 2010AngularJS от Google: шаблон связывается с данными, и при изменении данных страница обновляется сама.
  5. 2013React от Facebook (сейчас Meta): интерфейс описывается как функция от данных и собирается из компонентов.
  6. 2016Angular 2: фреймворк переписан с нуля на TypeScript. С этой версии название пишется без «JS»; AngularJS и Angular — разные продукты.
  7. 2019Хуки в React 16.8: состояние и эффекты описываются в обычных функциях. Так React пишут сейчас.
  8. 2023Сигналы в Angular 16: новый способ хранить состояние, после которого Angular сблизился с React по модели работы.
  9. 2025Вайбкодинг: Андрей Карпаты называет так работу, при которой код целиком пишет ИИ по описанию. Этому посвящена глава 0.3.
  10. 2026React Foundation: Meta передаёт React в Linux Foundation (24 февраля). Angular 22 (3 июня) делает стабильными Signal Forms и инструменты для ИИ-агентов.

В ленте видно, что React и Angular появились почти одновременно и решали одну задачу: как сделать, чтобы страница с меняющимися данными оставалась согласованной. За пятнадцать лет оба прошли через крупные переделки, и в 2026 году оба развиваются. Задача, ради которой они созданы, разобрана в следующем разделе на примере.

§3Состояние и интерфейс

Сравнение из жизни

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

Табло перерисовываются целиком, а фреймворк меняет на странице только изменившиеся элементы, иначе страница работала бы медленно.

Состояние — данные, которые описывают, что сейчас происходит в интерфейсе: какие товары в корзине, какой пункт меню открыт, что введено в поле поиска. В сравнении с аэропортом состояние — это расписание. Интерфейс — то, что пользователь видит на экране; в сравнении это табло. Задача фронтенда — чтобы интерфейс всегда соответствовал состоянию, сколько бы мест на экране ни показывали одни и те же данные.

Демонстрация: ручное обновление и обновление из состояния

Ниже две одинаковые витрины. Число товаров в корзине показано в трёх местах: значок в шапке, подпись на кнопке и строка «Итого». Цена показана в двух: в строке товара и в «Итого». В левой витрине каждое место обновляет отдельная строка кода — так писали с jQuery. В правой есть одна переменная состояния и одна функция, которая рисует витрину из неё. Под каждой витриной журнал показывает, какие изменения страницы выполнил код.

Корзина: ручное обновление и обновление из состоянияработает в браузере
Ручное обновление0
Кружка «Код без ошибок», 450 ₽
Итого: 0 шт. · 0 ₽

              
Из состояния0
Кружка «Код без ошибок», 450 ₽
Итого: 0 шт. · 0 ₽

              

Нажмите «В корзину» два раза, затем «Скидка 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.

Обновление из состояния · функция 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 Header Catalog Cart CartBadge ProductCard ProductCard ProductCard данные идут вниз: каждой карточке — её товар состояние корзины хранится в App

Голубым отмечены компоненты, которые показывают корзину. Состояние корзины хранится в общем родителе App, оба компонента получают его сверху. Когда карточка сообщает о покупке, App меняет состояние, и обе голубые части перерисовываются. Это та же модель, что в правой витрине из §3, разложенная по частям.

В React и в Angular компонент устроен по-разному, но содержит одни и те же части: описание того, как он выглядит, данные, которые он получает от родителя, и собственное состояние. Ниже один и тот же компонент — значок корзины из дерева — записан двумя способами. Переключатель в шапке страницы выбирает фреймворк; выбор запоминается и действует на всю книгу.

React · CartBadge.tsx
type Props = { count: number };

export function CartBadge({ count }: Props) {
  return <span className="badge">{count}</span>;
}
Angular · cart-badge.ts
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.

ЗадачаReactAngular
Компоненты и отрисовка из состояниясам 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 решают её одинаково по смыслу: интерфейс описывается как функция от состояния и собирается из компонентов, а фреймворк обновляет в браузере только изменившиеся места. Различаются они тем, сколько задач кроме отрисовки фреймворк берёт на себя.

Источники

  1. react.dev — Thinking in React
  2. angular.dev — Components
  3. angular.dev — Signals
  4. React Blog — React v16.8: The One With Hooks (6 февраля 2019)
  5. Linux Foundation — Announces the Formation of the React Foundation (24 февраля 2026)
  6. Ninja Squad — What's new in Angular 22.0 (3 июня 2026)
Справочник по Angular и React © Макаров Максим Николаевич