Как Node.js работает с файловой системой и какие библиотеки используются
Что проверяют
Понимаете ли вы, как файловые операции уживаются с однопоточным event loop и где на самом деле заканчивается асинхронность. Типичное продолжение: «как обработать файл на 5 ГБ» или «почему сервер подвис после readFileSync».
Как отвечать
Базовый инструмент это встроенный модуль node:fs. У него три стиля API:
- синхронный (
readFileSync,writeFileSync): блокирует event loop целиком. Уместен при старте приложения и в CLI-скриптах, но не в обработчике запроса; - колбэки (
fs.readFile(path, cb)): исторический стиль, ошибка приходит первым аргументом; - промисы (
node:fs/promises): основной вариант в современном коде, работает сasync/await.
Важная деталь: переносимого неблокирующего API для файлов у операционных систем нет, поэтому libuv выполняет файловые вызовы в пуле потоков. По умолчанию в нём 4 потока, размер меняется переменной UV_THREADPOOL_SIZE. Пул общий с crypto.pbkdf2, zlib и dns.lookup, так что массовые файловые операции тормозят совсем другие части приложения.
Для больших файлов нужны потоки: fs.createReadStream и createWriteStream, соединённые через pipeline из node:stream/promises. Он учитывает backpressure и закрывает потоки при ошибке. Пути собирают через node:path (path.join, path.resolve). В ES-модулях нет __dirname, вместо него import.meta.dirname в свежих версиях или fileURLToPath(import.meta.url).
Из библиотек стоит назвать fs-extra (удобные обёртки), chokidar (надёжное слежение за файлами поверх fs.watch) и glob. Часть их задач уже закрывает встроенный API: fs.rm и fs.mkdir с recursive: true, fs.cp.
Где спотыкаются
Вызывают readFileSync внутри обработчика HTTP-запроса. Пока файл читается, сервер не отвечает никому.
Читают большой файл целиком через readFile и получают рост памяти или падение процесса. Здесь нужен поток и построчная обработка через readline.
Проверяют существование через fs.existsSync, а потом открывают файл. Между проверкой и открытием файл могут удалить, поэтому правильнее сразу открывать и обрабатывать ошибку с кодом ENOENT.