Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «module resolution». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Module resolution** - процес, за яким Node.js знаходить фізичний файл модуля за іменем із `require()` чи `import`, проходячи послідовно вбудовані модулі, локальні шляхи й `node_modules` вгору по дереву директорій. **Ключове:** для пакетів Node.js читає `package.json` і бере точку входу з поля `"main"` (чи `"exports"` для сучасних пакетів).Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що таке "module resolution" > **Module resolution** - це процес, за допомогою якого Node.js **знаходить фізичний файл** (модуль) за іменем, указаним у `require()` чи `import`. Простіше кажучи: ```javascript const express = require('express'); ``` означає: > Node.js має знайти, де саме розташований модуль **express** - у ядрі, у `node_modules`, чи за локальним шляхом. ## 2. Загальна послідовність пошуку Коли Node.js зустрічає `require('щось')`, він проходить **п'ять етапів:** 1. Перевіряє, чи не є це **вбудованим (core)** модулем; 2. Перевіряє, чи не є це **шляхом до файлу** (`./`, `../`, `/`); 3. Інакше вважає, що це **модуль з** `node_modules`; 4. Шукає його в найближчих `node_modules` вгору по дереву директорій; 5. Якщо не знайдено - викидає помилку `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) ### Приклад: ```javascript const utils = require('./utils'); ``` Node.js робить таке: 1. Перевіряє, чи є `'./utils'` шляхом: - чи починається з `./`, `../` чи `/` - так. 2. Перетворює шлях в абсолютний: ```javascript /Users/tim/project/utils ``` 3. Пробує наступні варіанти (по порядку): ```javascript utils.js utils.json utils.node utils/index.js utils/index.json utils/index.node ``` 4. Якщо нічого не знайдено → помилка: ```javascript Error: Cannot find module './utils' ``` ## 5. Алгоритм для пакетів з `node_modules` Приклад: ```javascript const express = require('express'); ``` Node.js: 1. Шукає вбудований модуль `express` → немає. 2. Шукає `node_modules/express` у поточній папці. 3. Якщо не знайдено → піднімається вище по дереву: ```javascript /Users/tim/project/node_modules/express /Users/tim/node_modules/express /Users/node_modules/express /node_modules/express ``` 4. Знайшов → читає файл `express/package.json`. 5. У ньому шукає поле `"main"`: ```javascript { "name": "express", "main": "index.js" } ``` 6. Завантажує `/node_modules/express/index.js`. ## 6. Приклад візуально ```javascript project/ │ ├── app.js ├── utils/ │ └── index.js └── node_modules/ └── lodash/ ├── package.json └── lodash.js ``` ```javascript require('./utils'); // → ./utils/index.js require('lodash'); // → ./node_modules/lodash/lodash.js require('fs'); // → вбудований модуль Node.js ``` ## 7. Як Node.js обирає між `.js`, `.json` і `.node` Node пробує розширення **в такому порядку**: 1. `.js` - звичайний JavaScript-файл; 2. `.json` - автоматично парситься в об'єкт; 3. `.node` - бінарний нативний модуль (C++). Приклад: ```javascript require('./config'); // спробує config.js → config.json → config.node ``` ## 8. Module resolution для **ES Modules (ESM)** Для ESM (`import/export`) алгоритм інший - **суворіший**: - Потрібно вказувати **точне розширення** (`.js`, `.mjs`, `.json`); - Папки з `index.js` не шукаються автоматично; - `__dirname` та `__filename` відсутні; - `"exports"` у `package.json` визначає доступні шляхи. Приклад: ```javascript import utils from './utils/index.js'; // обов'язково з розширенням ``` ## 9. Як `package.json` впливає на module resolution Node.js дивиться на поля: | Поле | Призначення | |---|---| | `"main"` | Головна точка входу для CommonJS | | `"exports"` | Сучасна альтернатива для ESM / CJS | | `"type"` | Визначає тип модулів (`commonjs` чи `module`) | Приклад: ```javascript { "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`: ```javascript console.log(require.cache); ``` Повторний `require()` не виконує файл заново - просто повертає його `exports` із кешу. Це прискорює завантаження й запобігає рекурсивним циклам (`circular dependencies`). ## 11. Інструменти для налагодження resolution Якщо хочеш подивитися, **звідки** саме підхоплюється модуль: ```javascript node -p "require.resolve('express')" ``` Приклад виводу: ```javascript /Users/tim/project/node_modules/express/index.js ``` Чи для локального файлу: ```javascript node -p "require.resolve('./utils')" ``` ## Одним реченням > **Module resolution** - це механізм, за допомогою якого Node.js визначає, де фізично знаходиться модуль, указаний у `require()` чи `import`, проходячи через вбудовані, локальні й `node_modules`, поки не знайде потрібний файл.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.