Первая программа на Node.js
Play ITЗагрузка интерактивного демо…
Первая программа на Node.js
В браузере JavaScript ограничен правилами безопасности: нельзя слушать произвольный порт или читать файлы на диске без разрешения. Node.js запускает тот же язык как обычную программу на компьютере или сервере — с доступом к сети, файловой системе и процессам.
Практикум идёт по шагам — консоль и npm, встроенный http, затем Express и учебное REST API "Заметки".
| Шаг | Тема | Зачем |
|---|---|---|
| 1 | node -v, терминал | Убедиться, что среда готова |
| 2 | Файл .js и node app.js | Первая программа вне браузера (схемы запуска) |
| 3 | REPL | Быстрые эксперименты в консоли |
| 4 | process.argv, readline | CLI-утилиты и ввод пользователя |
| 5 | package.json, npm run | Манифест проекта и скрипты |
| 6 | http.createServer | HTTP без фреймворка |
| 7 | Express REST API | Маршруты, JSON, middleware |
| Материал | Зачем |
|---|---|
| Node.js — серверный JavaScript | Event loop, модули CJS/ESM |
| npm | install, scripts, lock, audit |
| Структура проекта | src/, env, конвенции |
| fs и http | Встроенные модули без Express |
| Точка входа — require.main | Прямой node file.js vs import |
| Express — middleware | Router, CORS, ошибки |
| Справочник по Node | Справочник API Node |
| Fullstack | CORS, прокси, два порта |
Навигация по блоку Node.js
- Вы здесь: Первая программа на Node.js
- Устройство runtime: Node.js - серверный JavaScript
- npm и структура: npm — команды, зависимости и lock-файлы, Структура Node-проекта и правила разработки
- Следующий шаг: Встроенные модули Node.js — fs, потоки и http → Express — middleware, маршруты и ошибки
- Склейка с фронтендом: Fullstack на JavaScript — API и фронтенд
Команды удобно выполнять во вкладке Терминал VS Code (Ctrl+`). Отладка и работа с IDE — статья "Отладка".
Шаг 1 — проверка установки
Скачайте LTS с nodejs.org и проверьте версии:
node -v
npm -v
Команда node -v показывает версию runtime (для новых проектов берите LTS 20 или 22). npm -v — менеджер пакетов из той же установки. Если терминал пишет, что node не найден, проверьте PATH — см. статью про Node.js.
Создайте рабочую папку, например notes-api, и откройте её в редакторе — дальше все команды выполняются из неё.
Шаг 2 — программа из файла
Файл hello.js (кодировка UTF-8):
console.log('Привет, мир!');
Запуск:
node hello.js
Разбор:
nodeпередаёт файл интерпретатору V8; браузер здесь не участвует.- Расширение
.jsв команде можно опустить:node helloтоже сработает. console.logпишет в stdout — стандартный поток вывода консоли.
Сохраняйте исходники в UTF-8. Node.js сам преобразует текст при выводе в консоль; кириллица в console.log обычно отображается корректно.
Шаг 3 — интерактивный режим (REPL)
Команда node без аргументов открывает REPL — read-eval-print loop:
node
> 10 + 12 * 2
34
> console.log('test')
test
undefined
> .exit
Разбор:
- Каждое выражение выполняется сразу после Enter — удобно для калькулятора и проверки синтаксиса.
console.logвозвращаетundefined, поэтому REPL печатает его на отдельной строке.- Последний результат доступен в переменной
_(одно подчёркивание). - Выход:
.exit,Ctrl+Dили дваждыCtrl+C.
REPL подходит для коротких экспериментов; полноценные программы храните в файлах.
Шаг 4 — аргументы командной строки и ввод с клавиатуры
process.argv
При запуске node script.js arg1 arg2 массив process.argv содержит путь к node, путь к скрипту и переданные аргументы:
// argv-demo.js
console.log(process.argv);
node argv-demo.js --help version
Первые два элемента — служебные; пользовательские аргументы начинаются с индекса 2. Значение с пробелами передавайте в кавычках: node app.js "hello world".
readline — диалог в консоли
Для интерактивного ввода после старта программы:
// ask.js
import readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
const rl = readline.createInterface({ input, output });
const name = await rl.question('Как вас зовут? ');
console.log(`Здравствуйте, ${name}!`);
await rl.close();
Разбор:
readline/promisesдаётawait rl.question()вместо колбэков.stdin/stdoutсвязывают интерфейс с консолью.rl.close()освобождает ресурсы; без этого процесс может не завершиться.
Более сложные CLI-примеры — в простых приложениях на JavaScript.
Завершение процесса
process.exitCode = 1; // код ошибки для ОС (0 — успех)
// или немедленно:
process.exit(1);
Перед process.exit() дождитесь вывода в консоль: буфер stdout может не успеть сброситься.
Шаг 5 — package.json и npm-скрипты
Превратите каталог в npm-пакет:
npm init -y
Флаг -y создаёт package.json с значениями по умолчанию. Основные поля:
| Поле | Смысл |
|---|---|
name | Имя пакета |
version | SemVer (1.0.0) |
main | Точка входа (index.js) |
scripts | Команды для npm run |
dependencies | Пакеты для runtime |
devDependencies | Инструменты разработки |
Добавьте ESM и скрипт запуска:
{
"name": "notes-api",
"type": "module",
"scripts": {
"hello": "node hello.js"
}
}
npm run hello
Разбор:
"type": "module"включаетimport/export(Node.js 18+).npm run <имя>ищет команду вscriptsи добавляет вPATHкаталогnode_modules/.bin.npm install <пакет>записывает зависимость вpackage.json;npm installбез аргументов восстанавливает всё из манифеста.
Шаг 6 — HTTP-сервер на встроенном http
Express строится поверх модуля http. Полезно один раз собрать сервер без фреймворка — так видно, что Express добавляет поверх createServer.
Файл server-raw.js:
Код ITЗагрузка примера кода…
node server-raw.js
curl http://127.0.0.1:3000/health
Разбор:
http.createServerпринимает callback(req, res)на каждый запрос.req.methodиreq.url— метод HTTP и путь без хоста.res.writeHeadзадаёт статус и заголовки;res.endотправляет тело и закрывает ответ.- Маршрутизацию, разбор JSON и middleware приходится писать вручную — Express берёт это на себя.
Подробный разбор http, потоков и req/res — во встроенных модулях Node.js.
Шаг 7 — REST API на Express
Логичный шаг после синтаксиса JS и async/await — поднять HTTP-сервер, который отвечает JSON. Express даёт маршруты, middleware и удобные req / res поверх http.
Мы соберём REST API "Заметки" — тот же учебный сценарий, что в Gin и Ktor. Данные пока в памяти: после перезапуска список пустой.
Что такое REST в двух словах
REST — стиль API, где ресурсы имеют URL, а действие задаёт HTTP-метод:
| Метод | Обычный смысл | В нашем API |
|---|---|---|
| GET | Прочитать | Список или одна заметка |
| POST | Создать | Новая заметка в теле JSON |
| DELETE | Удалить | Заметка по id в пути |
Что получится
| Метод | Путь | Действие |
|---|---|---|
| GET | /health | Сервер жив |
| GET | /notes | Список заметок |
| POST | /notes | Тело { "text": "..." } — создать |
| DELETE | /notes/:id | Удалить по id |
Инициализация проекта
npm install express
npm install -D nodemon
Обновите package.json:
{
"name": "notes-api",
"type": "module",
"scripts": {
"dev": "nodemon server.js",
"start": "node server.js"
}
}
| Поле / пакет | Смысл |
|---|---|
express | Маршруты и middleware |
nodemon | Перезапуск при сохранении файла |
npm run dev | Разработка с watch |
npm start | Обычный запуск |
Минимальный сервер Express
Файл server.js — точка входа.
express()— объект приложения.app.use(express.json())— разбор JSON-тела вreq.body.- Маршруты — обработчики, которые срабатывают, когда совпали URL и HTTP-метод.
app.listen(PORT)— слушать порт (по умолчанию 3000).
Код ITЗагрузка примера кода…
Запуск: npm run dev. Остановка — Ctrl+C. Подробнее про dev-сервер и браузер — Запуск и перезапуск приложений.
Разбор фрагментов
| Код | Смысл |
|---|---|
_req | Параметр не используем, сигнатура нужна |
req.body?.text | Optional chaining |
?? '' | Замена null/undefined на пустую строку |
return res.status(400)... | Прерывание обработчика |
201 | Created — ресурс создан |
req.params.id | Часть URL /notes/:id |
204 | Успех без тела (DELETE) |
process.env.PORT | Порт из окружения (хостинг) |
Проверка через curl
curl http://127.0.0.1:3000/health
curl http://127.0.0.1:3000/notes
curl -X POST http://127.0.0.1:3000/notes \
-H "Content-Type: application/json" \
-d "{\"text\": \"Изучить Node\"}"
curl http://127.0.0.1:3000/notes
curl -X DELETE http://127.0.0.1:3000/notes/1
Connection refused — сервер не запущен. Пустой req.body — нет express.json() или заголовка Content-Type: application/json.
Middleware — цепочка до маршрута
Middleware — функция (req, res, next). Express вызывает их по порядку регистрации.
| Middleware | Задача |
|---|---|
express.json() | Разобрать JSON-тело |
| Логирование | method, url, время |
cors | Браузерный фронт с другого порта — Express — middleware, маршруты и ошибки |
Пример логирования:
app.use((req, res, next) => {
const started = Date.now();
res.on('finish', () => {
console.log(req.method, req.url, res.statusCode, `${Date.now() - started}ms`);
});
next();
});
Подробнее: Express 263.
Router — вынести маршруты
routes/notes.js:
Код ITЗагрузка примера кода…
В server.js: app.use('/notes', createNotesRouter(store)); — router.get('/') + префикс /notes = GET /notes.
Частые ошибки
| Симптом | Причина | Что сделать |
|---|---|---|
node не найден | Node не в PATH | Переустановить или добавить путь — Node.js - серверный JavaScript |
Cannot find module 'express' | Нет npm install | npm install в каталоге проекта |
req.body undefined | Нет express.json() | Middleware выше маршрутов; curl с -H Content-Type |
| DELETE не находит id | Неверный шаблон пути | /notes/:id, читать req.params.id |
| Изменения не видны | Запущен node, не nodemon | npm run dev |
| CORS в браузере | Фронт :5173, API :3000 | Express — middleware, маршруты и ошибки или Fullstack на JavaScript — API и фронтенд |
Что попробовать дальше
- Центральный
errorHandler— Express — middleware, маршруты и ошибки. - SQLite / Prisma — заметки переживут перезапуск.
- React +
fetch— 272, Fullstack на JavaScript — API и фронтенд, Fetch / axios — типовые запросы, галерея компонентов (блок список с API). - Тесты supertest — Тестирование JavaScript — Vitest и Testing Library.
Как превратить учебный API в рабочий сервис
План эволюции
- In-memory store для отладки маршрутов.
- Подключение БД и миграций.
- Единый формат ошибок и валидация входных данных.
- Тесты на ключевые сценарии.
- Логи, метрики и контролируемое завершение процесса.
Базовые контракты API
| Эндпоинт | Успех | Ошибка клиента | Ошибка сервера |
|---|---|---|---|
GET /notes | 200 + массив | 400 при неверных параметрах | 500 |
POST /notes | 201 + объект | 400 при пустом text | 500 |
DELETE /notes/:id | 204 | 404, если id не найден | 500 |
Связанные материалы
| Тема | Материал |
|---|---|
| Express углублённо | Express — middleware, маршруты и ошибки |
| Fullstack | Fullstack на JavaScript — API и фронтенд |
| TypeScript на сервере | TypeScript |
| Теория Node | Node.js - серверный JavaScript |
Для боевого сервера — process manager (PM2, systemd), секреты в переменных окружения, HTTPS за reverse proxy (Nginx, Caddy).
Пример proxy_pass и заголовков — Nginx — конфиги под задачу.
Данные в памяти теряются при перезапуске — нужна БД и бэкапы.
Базовый разбор HTTP и HTTPS — HTTP как основа веб-интеграций.
В подборках
Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:
Первые шаги (маршрут подборки) — Первая программа на TypeScript, Первая программа на Kotlin, Первая программа на C++, Первая программа на Ruby, Первая программа на C#, Первая программа на Rust.