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, поки не знайде потрібний файл.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.