module resolution
1. Що таке "module resolution"
Module resolution - це процес, за допомогою якого Node.js знаходить фізичний файл (модуль) за іменем, указаним у
require()чиimport.
Простіше кажучи:
const express = require('express');означає:
Node.js має знайти, де саме розташований модуль express - у ядрі, у
node_modules, чи за локальним шляхом.
2. Загальна послідовність пошуку
Коли Node.js зустрічає require('щось'), він проходить п'ять етапів:
- Перевіряє, чи не є це вбудованим (core) модулем;
- Перевіряє, чи не є це шляхом до файлу (
./,../,/); - Інакше вважає, що це модуль з
node_modules; - Шукає його в найближчих
node_modulesвгору по дереву директорій; - Якщо не знайдено - викидає помилку
MODULE_NOT_FOUND.
3. Типи модулів, які Node.js вміє розв'язувати
| Тип | Приклад | Опис |
|---|---|---|
| Core (вбудовані) | fs, path, os, http | Вбудовані в Node.js - не потребують встановлення |
| Локальні файли | ./utils.js, ../config.json | Твої власні файли |
| Пакети (npm) | express, chalk, mongoose | Шукаються в node_modules |
| JSON / бінарні | config.json, addon.node | Автоматично парсяться чи завантажуються як бінарні |
4. Алгоритм module resolution (для CommonJS)
Приклад:
const utils = require('./utils');Node.js робить таке:
- Перевіряє, чи є
'./utils'шляхом:
- чи починається з
./,../чи/- так.
- Перетворює шлях в абсолютний:
/Users/tim/project/utils- Пробує наступні варіанти (по порядку):
utils.js
utils.json
utils.node
utils/index.js
utils/index.json
utils/index.node- Якщо нічого не знайдено → помилка:
Error: Cannot find module './utils'5. Алгоритм для пакетів з node_modules
Приклад:
const express = require('express');Node.js:
- Шукає вбудований модуль
express→ немає. - Шукає
node_modules/expressу поточній папці. - Якщо не знайдено → піднімається вище по дереву:
/Users/tim/project/node_modules/express
/Users/tim/node_modules/express
/Users/node_modules/express
/node_modules/express- Знайшов → читає файл
express/package.json. - У ньому шукає поле
"main":
{
"name": "express",
"main": "index.js"
}- Завантажує
/node_modules/express/index.js.
6. Приклад візуально
project/
│
├── app.js
├── utils/
│ └── index.js
└── node_modules/
└── lodash/
├── package.json
└── lodash.jsrequire('./utils'); // → ./utils/index.js
require('lodash'); // → ./node_modules/lodash/lodash.js
require('fs'); // → вбудований модуль Node.js7. Як Node.js обирає між .js, .json і .node
Node пробує розширення в такому порядку:
.js- звичайний JavaScript-файл;.json- автоматично парситься в об'єкт;.node- бінарний нативний модуль (C++).
Приклад:
require('./config'); // спробує config.js → config.json → config.node8. Module resolution для ES Modules (ESM)
Для ESM (import/export) алгоритм інший - суворіший:
- Потрібно вказувати точне розширення (
.js,.mjs,.json); - Папки з
index.jsне шукаються автоматично; __dirnameта__filenameвідсутні;"exports"уpackage.jsonвизначає доступні шляхи.
Приклад:
import utils from './utils/index.js'; // обов'язково з розширенням9. Як package.json впливає на module resolution
Node.js дивиться на поля:
| Поле | Призначення |
|---|---|
"main" | Головна точка входу для CommonJS |
"exports" | Сучасна альтернатива для ESM / CJS |
"type" | Визначає тип модулів (commonjs чи module) |
Приклад:
{
"name": "my-lib",
"main": "./dist/index.cjs",
"exports": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"type": "module"
}Node буде використовувати "exports" замість "main",
якщо воно вказане - це сучасний спосіб контролювати, які файли можна імпортувати ззовні.
10. Кешування під час module resolution
Коли Node.js розв'язав модуль і завантажив його, результат зберігається в require.cache:
console.log(require.cache);Повторний require() не виконує файл заново - просто повертає його exports із кешу.
Це прискорює завантаження й запобігає рекурсивним циклам (circular dependencies).
11. Інструменти для налагодження resolution
Якщо хочеш подивитися, звідки саме підхоплюється модуль:
node -p "require.resolve('express')"Приклад виводу:
/Users/tim/project/node_modules/express/index.jsЧи для локального файлу:
node -p "require.resolve('./utils')"Одним реченням
Module resolution - це механізм, за допомогою якого Node.js визначає, де фізично знаходиться модуль, указаний у
require()чиimport, проходячи через вбудовані, локальні йnode_modules, поки не знайде потрібний файл.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.