Node.js — это среда выполнения JavaScript вне браузера: она берёт тот же язык, на котором вы пишете интерфейсы, и позволяет запускать его на сервере, в терминале и на вашем компьютере. На Node.js работают API и бэкенды, чаты, консольные утилиты и почти весь современный фронтенд-инструментарий — от npm до Vite. Понимание того, из чего состоит Node и чем он отличается от браузера, избавит вас от множества ошибок в следующих темах.
Из чего состоит Node.js
Node.js — не язык и не фреймворк, а среда выполнения (runtime): программа, которая читает ваш .js-файл и выполняет его. Её создал Райан Даль в 2009 году, соединив быстрый JavaScript-движок из Chrome с библиотекой асинхронного ввода-вывода. Внутри Node четыре основных слоя:
| Компонент | Язык | Что делает |
|---|---|---|
| V8 | C++ | Движок JavaScript из Chrome: разбирает код, компилирует его в машинный код (JIT), управляет памятью и сборкой мусора |
| libuv | C | Event loop и асинхронный ввод-вывод: файлы, сеть, таймеры, пул потоков; одинаково работает в Linux, macOS и Windows |
| C++-привязки (bindings) | C++ | «Мост» между JavaScript и системными библиотеками: когда вы вызываете fs.readFile, привязка передаёт запрос в libuv |
| Стандартная библиотека | JavaScript | Встроенные модули node:fs, node:http, node:path, node:crypto, node:os и другие |
Кроме того, в Node встроены OpenSSL (шифрование и HTTPS), llhttp (разбор HTTP), undici (реализация fetch), ICU (поддержка языков и дат) и другие библиотеки. Версии всех компонентов хранятся в объекте process.versions — его удобно смотреть однострочником node -p, о котором подробнее в теме «REPL и запуск скриптов»:
node -p "process.versions"{
node: '24.21.0',
acorn: '8.18.0',
...
openssl: '3.5.8',
undici: '7.29.1',
uv: '1.52.1',
v8: '13.6.233.17-node.53',
...
}Здесь видно, что Node 24.21 работает на V8 13.6 и libuv 1.52. Версия V8 определяет, какие новые возможности JavaScript доступны: если движок поддерживает синтаксис, его поддерживает и Node.
💡 Упрощённо: V8 отвечает за то, как выполнить JavaScript, а libuv — за то, как дождаться диска и сети, не останавливая программу. Как именно это работает, разберём в теме «Event loop в Node.js».
Первый скрипт
Для скрипта не нужны HTML и браузер — только файл и терминал. Создайте в любой папке файл hello.js:
console.log('Hello from Node.js!');
console.log(2 + 3);
console.log(`Node version: ${process.version}`);
console.log(`Platform: ${process.platform}, architecture: ${process.arch}`);Запустите его командой node с именем файла (терминал должен находиться в той же папке):
node hello.jsHello from Node.js!
5
Node version: v24.21.0
Platform: linux, architecture: x64console.log выводит текст не в консоль DevTools, а прямо в терминал. process.version — версия Node, process.platform — операционная система (linux, darwin для macOS, win32 для Windows), process.arch — архитектура процессора. У вас значения могут отличаться. Когда код в файле заканчивается и ждать больше нечего, Node сам завершает процесс.
Что умеет Node, но не умеет браузер
Браузер из соображений безопасности держит страницу в «песочнице»: она не может свободно читать файлы на диске или узнать имя пользователя. У Node таких ограничений нет — у скрипта те же права, что у вашего пользователя в системе. Сохраните этот пример в файл files.mjs (расширение .mjs говорит Node, что это ES-модуль с import; подробнее — в теме «ES-модули в Node.js»):
import { writeFile, readFile } from 'node:fs/promises';
import os from 'node:os';
await writeFile('note.txt', 'Written by Node.js'); // создаём файл на диске
const text = await readFile('note.txt', 'utf8'); // читаем его обратно
console.log(text);
console.log(`OS: ${os.type()}, CPU cores: ${os.availableParallelism()}`);
console.log(`Home folder: ${os.homedir()}`);Written by Node.js
OS: Linux, CPU cores: 4
Home folder: /home/ayselПосле запуска рядом со скриптом появится файл note.txt. Встроенные модули подключаются с префиксом node: — так сразу видно, что это часть Node, а не пакет из npm. Модуль node:fs/promises работает с файлами, node:os — с информацией о системе.
Node.js и браузер: общий язык, разное окружение
Язык один и тот же — стандарт ECMAScript: переменные, функции, классы, промисы, async/await работают одинаково. Различается окружение — набор глобальных объектов и API, которые даёт среда:
| Браузер | Node.js | |
|---|---|---|
| Глобальный объект | window (и globalThis) | globalThis (старое имя — global) |
| Страница и DOM | document, querySelector, события кликов | нет |
| Диалоги | alert, prompt, confirm | нет |
| Файловая система | нет (только через выбор файла пользователем) | node:fs |
| Информация о процессе | нет | process: версия, переменные окружения, аргументы |
| Двоичные данные | ArrayBuffer, Blob | то же + Buffer |
| Общие Web API | fetch, URL, setTimeout, console, structuredClone, AbortController | те же самые |
Проверим это на практике. Файл globals.js:
console.log(typeof window); // → undefined
console.log(typeof document); // → undefined
console.log(typeof globalThis); // → object
console.log(globalThis === global); // → true
console.log(typeof process, typeof Buffer); // → object function
console.log(typeof fetch, typeof setTimeout); // → function functionglobalThis — стандартное имя глобального объекта, которое работает везде: в браузере, в Node, в воркерах. Используйте его, когда пишете код, который должен запускаться в обеих средах. Многие Web API (fetch, URL, TextEncoder, AbortController, crypto.randomUUID) в Node встроены и ведут себя так же, как в браузере, поэтому знания из фронтенда переносятся напрямую.
⚠️ Раз у скрипта полный доступ к файлам и сети, запускайте только код, которому доверяете. Скрипт из случайного репозитория может прочитать ваши ключи из домашней папки или удалить файлы — браузерной «песочницы» здесь нет.
Где применяют Node.js
Node особенно хорош там, где программа много ждёт: ответа базы данных, файла, сети. Пока одна операция ждёт, Node обслуживает другие, поэтому один процесс держит тысячи одновременных соединений. Вот так выглядит минимальный веб-сервер (файл server.mjs):
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`Hello from Node.js ${process.version}!\n`);
});
server.listen(3000, () => {
console.log('Server is running at http://localhost:3000');
});Запустите node server.mjs и откройте http://localhost:3000 в браузере — вы увидите Hello from Node.js v24.21.0!. В отличие от hello.js, этот процесс не завершается: сервер ждёт новых запросов, пока вы не нажмёте Ctrl+C. Модуль http подробно разберём в отдельном разделе.
Типичные области применения:
- API и бэкенды — REST и GraphQL-серверы на Express, Fastify, NestJS.
- Real-time — чаты, уведомления, совместное редактирование, онлайн-игры на WebSocket и Socket.IO.
- CLI-утилиты — npm, ESLint, Prettier, TypeScript-компилятор и сотни других инструментов написаны для Node.
- SSR и фулстек-фреймворки — Next.js, Nuxt, Astro рендерят страницы на сервере с помощью Node.
- Инструменты сборки — Vite, webpack, Rollup: любой современный фронтенд-проект собирается в Node.
- Десктоп — Electron (на нём сделан VS Code) объединяет Node и Chromium.
Где Node слаб
JavaScript в Node выполняется в одном основном потоке. Если код долго что-то вычисляет — сжимает видео, считает сложную математику, обрабатывает большие изображения, — поток занят, и все остальные запросы ждут. Для таких задач в Node есть worker_threads (отдельная тема курса) или выносят вычисления в сервис на другом языке. Ориентир простой: много ввода-вывода и сети — Node подходит отлично; тяжёлые вычисления в каждом запросе — нужен другой подход.
Типичные ошибки
1. Браузерные объекты в Node. Код с document или window падает сразу:
document.querySelector('h1'); // ❌ ReferenceError: document is not definedВ Node нет страницы и DOM. Для глобального объекта используйте globalThis, а код, который работает с DOM, запускайте в браузере.
2. Node-модули во фронтенд-коде. Обратная ситуация: import fs from 'node:fs' в скрипте, подключённом к HTML-странице, не заработает — у браузера нет доступа к файловой системе. Код для сервера и код для браузера живут в разных средах, даже если написаны на одном языке.
3. «Node.js — это фреймворк» или «язык». Node — среда выполнения. Язык — JavaScript (или TypeScript, который компилируется в JavaScript). Фреймворки — Express, Fastify, NestJS — это npm-пакеты, которые работают поверх Node.
4. Тяжёлые вычисления прямо в обработчике запроса. Цикл на несколько секунд в обработчике HTTP-запроса «замораживает» сервер для всех пользователей. Такие задачи выносят в worker threads, очереди фоновых задач или отдельные сервисы.
Итог
- Node.js — среда выполнения JavaScript вне браузера, а не язык и не фреймворк.
- Основа Node: движок V8 выполняет JavaScript, libuv отвечает за event loop и асинхронный ввод-вывод, C++-привязки связывают их со стандартной библиотекой.
- Скрипт запускается командой
node файл.js; версии компонентов — вprocess.versionиprocess.versions. - В Node нет
window,documentиalert, зато естьglobalThis,process,Bufferи доступ к файлам, сети и ОС. - Многие Web API (
fetch,URL,setTimeout,AbortController) работают так же, как в браузере. - Node силён в задачах с большим количеством ввода-вывода (API, real-time, CLI, SSR, сборка) и слаб в тяжёлых вычислениях в основном потоке.
Практика
- Создайте
about.js, который выводит версию Node, версии V8 и libuv, платформу и архитектуру процессора в виде аккуратных строк видаV8: 13.6.233.17-node.53. - Напишите
env-check.js, который определяет среду выполнения: еслиtypeof window !== 'undefined', выводит «Browser», еслиtypeof process !== 'undefined'— «Node.js». Запустите его в Node и вставьте тот же код в консоль DevTools браузера. - Напишите
system-info.mjs, который собирает объект с платформой, количеством ядер, объёмом свободной памяти в гигабайтах и домашней папкой и сохраняет его в файлsystem-info.json. - Небольшая задача: доработайте
server.mjsтак, чтобы по адресу/сервер отвечал приветствием, а по адресу/info— JSON с версией Node, платформой и временем работы процесса (process.uptime()).
💡 В задании 3 пригодятся
os.freemem()(байты),JSON.stringify(data, null, 2)иwriteFileизnode:fs/promises. В задании 4 адрес запроса лежит вreq.url, а для JSON отправьте заголовокContent-Type: application/json.