Создано искусственным интеллектомУлучшено людьми
Riqli · живые документы · обновляются постоянно
Где знания об искусственном интеллекте встречаются с человеческой практикой.
Поделиться с друзьями

Backend на Node.js
Введение в Backend-разработку на Node.js
Аннотация: Node.js — это среда выполнения JavaScript, позволяющая использовать язык, знакомый фронтенд-разработчикам, для создания серверной логики, API и интеграций с базами данных . Backend отвечает за обработку данных, бизнес-логику, аутентификацию и взаимодействие с хранилищами, в то время как frontend отвечает за визуальное представление и взаимодействие с пользователем .
Цель: Сформировать у слушателей практические навыки создания серверных приложений на Node.js, начиная от настройки окружения и заканчивая развертыванием базового API, готового к масштабированию .
Результаты обучения:
- Настройка рабочего окружения Node.js и управление зависимостями через npm .
- Создание HTTP-сервера с использованием встроенного модуля
httpи фреймворка Express . - Реализация маршрутизации, обработка запросов и ответов в формате JSON .
- Понимание middleware и его роли в обработке входящих данных .
- Взаимодействие backend с frontend-приложением (на примере Angular) .
Целевая аудитория: Frontend-разработчики, желающие освоить серверную разработку; начинающие backend-разработчики, имеющие базовые знания JavaScript и желающие изучить экосистему Node.js .
Настройка окружения и создание проекта. Для начала работы с Node.js необходимо установить среду выполнения с официального сайта nodejs.org и убедиться в наличии пакетного менеджера npm, который поставляется вместе с Node.js . Проверить установку можно командами node -v и npm -v в терминале .
Создание нового проекта начинается с инициализации файла package.json, который управляет зависимостями и скриптами. Команда npm init -y создает базовую конфигурацию с настройками по умолчанию . Далее устанавливаются необходимые пакеты: Express для создания веб-сервера, body-parser для обработки JSON-запросов, dotenv для работы с переменными окружения и nodemon как dev-зависимость для автоматического перезапуска сервера при изменениях кода .
Установка выполняется командами: npm install express body-parser dotenv и npm install --save-dev nodemon . Файл package.json после установки будет содержать секцию dependencies с указанием версий установленных пакетов.
Какая команда используется для инициализации нового Node.js-проекта с настройками по умолчанию?
npm init -y
Команда npm init -y создает файл package.json с конфигурацией по умолчанию, пропуская интерактивный опрос .
npm start
node init
npm install --init
Создание HTTP-сервера и маршрутизация. В Node.js существует два основных подхода к созданию сервера: использование встроенного модуля http и применение фреймворка Express .
Встроенный модуль http требует ручной обработки URL, методов запроса и парсинга данных. Пример простого сервера: const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World'); }); server.listen(3000); . При таком подходе разработчик самостоятельно реализует маршрутизацию, проверяя req.url и req.method .
Express упрощает эту задачу, предоставляя методы app.get(), app.post(), app.put(), app.delete() для определения маршрутов . Пример сервера на Express: const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Welcome to my backend!'); }); app.listen(3000); . Express также автоматически обрабатывает заголовки и предоставляет удобные методы для отправки JSON-ответов через res.json() .
Какой метод Express используется для определения обработчика GET-запроса?
app.get()
Метод app.get() регистрирует маршрут для обработки HTTP GET-запросов по указанному пути .
app.route()
app.request()
app.handler()
Middleware и обработка данных. Middleware — это функции, которые выполняются между получением запроса и отправкой ответа . Они имеют доступ к объектам запроса (req), ответа (res) и функции next, которая передает управление следующему middleware .
Пример middleware для логирования: app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); }); . Этот код выводит в консоль метод и URL каждого входящего запроса.
Для обработки JSON-данных, приходящих в теле POST-запросов, используется express.json() или body-parser: app.use(express.json()); . После подключения этого middleware данные становятся доступны в req.body. Пример обработки POST-запроса: app.post('/data', (req, res) => { const data = req.body; res.json({ message: 'Data received', data }); }); .
Что делает функция next() в middleware Express?
Передает управление следующему middleware или обработчику маршрута
next() вызывается для передачи управления следующей функции в цепочке middleware. Без вызова next() запрос «зависает» и не доходит до обработчика .
Завершает обработку запроса и отправляет ответ
Парсит тело запроса в формате JSON
Логирует информацию о запросе в консоль
Взаимодействие с frontend на примере Angular. Backend-сервер на Node.js может обслуживать запросы от frontend-приложения, построенного на Angular . Типичный сценарий: Angular-приложение отправляет HTTP-запрос на сервер для авторизации и получения защищенных данных .
Пример: при нажатии кнопки «Авторизоваться» Angular вызывает метод сервиса, который отправляет POST-запрос на сервер с учетными данными. Сервер проверяет данные и возвращает токен . Полученный токен сохраняется на клиенте и используется для последующих запросов к защищенным эндпоинтам .
Для защиты маршрутов на сервере применяется middleware, которое проверяет наличие и валидность токена в заголовке Authorization . Если токен отсутствует или недействителен, сервер возвращает статус 401 (Unauthorized) . Пример middleware для проверки JWT: const jwt = require('jsonwebtoken'); function authMiddleware(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ error: 'Missing token' }); } try { req.user = jwt.verify(authHeader.slice(7), process.env.JWT_SECRET); next(); } catch { res.status(401).json({ error: 'Invalid token' }); } } .
Какой HTTP-статус обычно возвращается при отсутствии или недействительности токена аутентификации?
401
Статус 401 (Unauthorized) сигнализирует клиенту о необходимости аутентификации. При недействительном токене middleware возвращает именно этот статус .
403
500
404
Инфраструктура и масштабирование
От монолита к микросервисам. На ранних этапах развития проекта Node.js-приложение обычно представляет собой монолит — единый сервис, обрабатывающий все запросы и содержащий всю бизнес-логику . Такой подход прост в разработке и развертывании: одна кодовая база, один процесс, одна база данных .
Однако по мере роста нагрузки и команды монолит становится узким местом: развертывание замедляется, баг в одной части системы может затронуть другие функции, а горизонтальное масштабирование требует дублирования всего приложения целиком . В этот момент команды начинают выделять отдельные сервисы: аутентификацию, платежи, уведомления .
Микросервисная архитектура позволяет независимо развертывать и масштабировать компоненты системы, но вносит новые сложности: сетевые вызовы заменяют внутренние вызовы функций, увеличивается задержка, отладка распределенных систем требует специальных инструментов .
Что является типичной причиной перехода от монолитной архитектуры к микросервисам?
Рост нагрузки и необходимость независимого развертывания компонентов
Монолит начинает ограничивать скорость разработки и масштабирования, когда разные части системы требуют разных темпов изменений и ресурсов .
Желание использовать несколько языков программирования в одном проекте
Требование использовать только реляционные базы данных
Необходимость уменьшить количество серверов в инфраструктуре
Контейнеризация и оркестрация. Для развертывания Node.js-приложений в production широко используется Docker — инструмент контейнеризации, позволяющий упаковать приложение вместе со всеми зависимостями в изолированный образ . Это гарантирует, что приложение будет работать одинаково в любой среде: на локальной машине разработчика, на тестовом сервере и в production .
Для управления множеством контейнеров применяется Kubernetes — система оркестрации, которая автоматически распределяет нагрузку, перезапускает упавшие контейнеры и масштабирует количество реплик в зависимости от трафика . Курсы по Node.js для профессионалов часто включают блок по Docker и Kubernetes, поскольку эти навыки востребованы в вакансиях уровня Middle и выше .
Процесс развертывания обычно автоматизируется через CI/CD-пайплайны: при каждом коммите в репозиторий запускаются тесты, собирается Docker-образ и развертывается новая версия приложения .
Какой инструмент используется для оркестрации контейнеров в production-среде Node.js-приложений?
Kubernetes
Kubernetes управляет контейнерами, обеспечивая их автоматический перезапуск, балансировку нагрузки и масштабирование .
npm
Express
Webpack
Архитектура и производительность Node.js-приложений
Однопоточность и Event Loop. Node.js построен на однопоточной модели с неблокирующим вводом-выводом. В отличие от традиционных серверных платформ, где каждый запрос обрабатывается в отдельном потоке, Node.js использует один главный поток для обработки JavaScript-кода и делегирует операции ввода-вывода системе . Когда приходит запрос, требующий чтения файла или обращения к базе данных, Node.js не блокирует основной поток в ожидании результата, а регистрирует callback и продолжает обработку других задач. Когда операция завершается, callback помещается в очередь событий (event queue) и выполняется, когда стек вызовов свободен .
Это означает, что любая синхронная операция в основном потоке блокирует обработку всех остальных запросов. Использование fs.readFileSync, crypto.pbkdf2Sync или длительных вычислений в основном потоке может «заморозить» сервер и привести к деградации производительности .
Кластеризация и Worker Threads. Поскольку Node.js по умолчанию использует только одно ядро процессора, для полноценного использования многоядерных систем применяется встроенный модуль cluster . Он позволяет создавать fork-процессы (воркеры) для каждого ядра, каждый из которых обрабатывает часть входящих запросов. Мастер-процесс распределяет нагрузку между воркерами, а в случае падения одного из них автоматически перезапускает его .
Для выполнения CPU-интенсивных задач без блокировки основного потока используются Worker Threads — легковесные потоки, разделяющие память с главным потоком, но выполняющие код параллельно . Это позволяет выносить вычисления, парсинг больших данных или обработку изображений в отдельный поток, не влияя на обработку HTTP-запросов.
В production-средах для управления кластерами часто применяется PM2 — процесс-менеджер, который умеет автоматически запускать несколько инстансов приложения, мониторить CPU и память, а также перезапускать упавшие процессы .
Кеширование и очереди задач. Для снижения нагрузки на базу данных и ускорения ответов API применяется кеширование на уровне памяти. Redis — наиболее распространённое решение для хранения сессий, кеша результатов запросов и временных данных . Типовой паттерн: перед обращением к БД сервер проверяет наличие данных в Redis; если данные есть, они возвращаются немедленно, минуя запрос к базе .
Для операций, не требующих немедленного результата (отправка email, генерация PDF, обработка изображений), используется механизм очередей задач. Пользователь создаёт заказ, сервер помещает задачу в очередь и немедленно возвращает ответ; воркер обрабатывает задачу асинхронно . Популярные библиотеки для организации очередей: bullmq, agenda, kue .
Какая из перечисленных операций может заблокировать Event Loop в Node.js?