Перейти к содержанию
Educora
Продвинутый22 мин23 / 27

Основы Node.js

Запускай JavaScript вне браузера: среда Node.js, модули CommonJS и ES, npm и `package.json`, работа с файлами через `fs` и `path`.

Проверь себя
В этом уроке ты узнаешь
  • Объяснять, что такое Node.js и чем он отличается от JavaScript в браузере
  • Создавать проект через npm, устанавливать пакеты и запускать скрипты из package.json
  • Использовать ES-модули и встроенные fs/promises, path, process для работы с файлами и аргументами командной строки

До 2009 года JavaScript жил только внутри браузеров. В том году Райан Дал (Ryan Dahl) взял движок V8 из Chrome и представил Node.js — среду, которая запускает JavaScript на серверах и обычных компьютерах. Сегодня на Node.js работают бэкенды (API), инструменты командной строки и даже настольные приложения: Vite, ESLint и Prettier работают на Node.js, а редактор VS Code построен на Electron, который основан на Node.js.

Что такое Node.js

Node.js = движок V8 + libuv (цикл событий и асинхронный ввод-вывод) + встроенные модули (fs, path, http, crypto и другие). Язык тот же, среда другая: нет document и window, зато есть файлы, сеть и процессы. Твой JavaScript по-прежнему работает в одном потоке со знакомым циклом событий, а тяжёлый ввод-вывод система выполняет в фоне.

БраузерNode.js
DOMесть (document)нет
Файлытолько если пользователь выберетполный доступ (fs)
Глобальный объектwindow / globalThisglobal / globalThis
МодулиES-модулиES-модули и CommonJS
Где работает кодна устройстве пользователяна сервере или твоём компьютере
  1. 1
    Установи

    Скачай версию LTS (долгосрочная поддержка) с сайта nodejs.org и установи её.

  2. 2
    Проверь

    В терминале набери node -v и npm -v — должны появиться версии.

  3. 3
    Создай файл

    Напиши в файле hello.js строку console.log('Hello from Node!');.

  4. 4
    Запусти

    node hello.js. Команда node без файла открывает интерактивную консоль (REPL); выйти — .exit.

Модули: ES и CommonJS

В Node.js две системы модулей. CommonJS (require и module.exports) — историческая, она повсюду в старых проектах. ES-модули (import/export) — стандарт, такой же, как в браузере. В новых проектах выбирай ES-модули: добавь в package.json строку "type": "module" или давай файлам расширение .mjs. Встроенные модули импортируй с префиксом node:: import fs from 'node:fs'.

JavaScript
// math.js
export const PI = 3.14159;
export function circleArea(r) {
  return PI * r * r;
}

// app.js
import { circleArea } from './math.js';
import os from 'node:os';

console.log(circleArea(2).toFixed(2));
console.log(`Platform: ${os.platform()}`);
Ожидаемый результат
12.57
Platform: win32
Запуск: node app.js; в Windows будет win32, в macOS — darwin, в Linux — linux.
CommonJSES-модули
Экспортmodule.exports = { circleArea }export function circleArea() {}
Импортconst { circleArea } = require('./math')import { circleArea } from './math.js'
Папка файла__dirnameimport.meta.dirname
await на верхнем уровненетесть

npm и package.json

npm (Node Package Manager) устанавливается вместе с Node.js и даёт доступ к реестру с миллионами пакетов. npm init -y создаёт package.json, npm install dayjs добавляет зависимость, а npm install -D vitest — зависимость только для разработки. Код пакетов попадает в папку node_modules, а package-lock.json фиксирует точные версии. npm run dev запускает команду из раздела scripts, а npx выполняет команду пакета без глобальной установки.

JSON
{
  "name": "notes-cli",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node notes.js",
    "test": "vitest"
  },
  "dependencies": {
    "dayjs": "^1.11.10"
  },
  "devDependencies": {
    "vitest": "^2.1.0"
  }
}
Версии записываются как major.minor.patch: ^1.11.10 разрешает любую более новую версию ниже 2.0.0, ~1.11.10 — только исправления 1.11.x, а 1.11.10 — только эту версию.

Файлы, пути и процесс

node:fs/promises даёт асинхронные функции для файлов: readFile, writeFile, mkdir, readdir. node:path правильно строит пути и в Windows (\), и в Linux и macOS (/). process.argv содержит аргументы командной строки, а process.env — переменные окружения. Маленькая программа ниже хранит заметки в JSON-файле.

JavaScript
// notes.js
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import path from 'node:path';

const dir = path.join(import.meta.dirname, 'data');
const file = path.join(dir, 'notes.json');
await mkdir(dir, { recursive: true });

let notes = [];
try {
  notes = JSON.parse(await readFile(file, 'utf8'));
} catch (error) {
  if (error.code !== 'ENOENT') throw error;
}

const text = process.argv.slice(2).join(' ') || 'Empty note';
notes.push({ id: notes.length + 1, text });
await writeFile(file, JSON.stringify(notes, null, 2));

console.log(`Saved note #${notes.length}: ${text}`);
console.log('File:', path.basename(file), '| notes:', notes.length);
Ожидаемый результат
Saved note #1: Buy bread
File: notes.json | notes: 1
Saved note #2: Call Leyla
File: notes.json | notes: 2
Сначала выполнено node notes.js Buy bread, затем node notes.js Call Leyla. ENOENT означает «файл не найден» — при первом запуске это нормально.

Чтобы сделать веб-сервер на Node.js, даже библиотека не нужна — хватит встроенного модуля node:http. В реальных проектах обычно используют фреймворки вроде Express или Fastify, но все они построены на этой основе.

JavaScript
// server.js
import http from 'node:http';

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ message: 'Hello from Node', path: req.url }));
});

server.listen(3000, () => console.log('Server on http://localhost:3000'));
Ожидаемый результат
Server on http://localhost:3000
Открой в браузере http://localhost:3000/api/hello — ответ: {"message":"Hello from Node","path":"/api/hello"}. Чтобы остановить сервер, нажми в терминале Ctrl+C.
Задание

Здесь process.argv имитирует переменная argv. Напиши parseArgs(args): пары --ключ значение превращаются в { ключ: 'значение' }, а флаг без значения после него (--verbose) получает true.

Задание · JavaScript
const argv = ['node', 'app.js', '--city', 'Baku', '--days', '3', '--verbose'];

function parseArgs(args) {
  const options = {};
  // walk through args; --key value → options[key] = value, lone --flag → true
  return options;
}

console.log(parseArgs(argv.slice(2)));
console.log(parseArgs(['--help']));
▸ Ожидаемый результат
{ city: 'Baku', days: '3', verbose: true }
{ help: true }
Задание

Напиши satisfiesCaret(version, range): для диапазона вида ^1.4.0 версия должна иметь тот же номер major и быть не ниже версии из диапазона (особые правила для 0.x не учитывай).

Задание · JavaScript
function satisfiesCaret(version, range) {
  // compare major, then minor, then patch
}

for (const version of ['1.5.2', '1.4.0', '2.0.0', '1.3.9']) {
  console.log(version, satisfiesCaret(version, '^1.4.0'));
}
▸ Ожидаемый результат
1.5.2 true
1.4.0 true
2.0.0 false
1.3.9 false

Главное

  • Node.js = V8 + цикл событий (libuv) + встроенные модули: JavaScript без DOM, но с файлами, сетью и процессами.
  • В новых проектах используй ES-модули ("type": "module", префикс node:); require остаётся в старом коде.
  • package.json описывает проект: скрипты, dependencies, devDependencies; package-lock.json фиксирует версии, а node_modules не коммитят.
  • Semver — это major.minor.patch: ^ разрешает обновления minor и patch, ~ — только patch.
  • fs/promises, path и process отвечают за файлы, переносимые пути, аргументы и переменные окружения.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
Чего по умолчанию нет в Node.js?