Загрузка…
Загрузка…
Node.js · middle · сложность 4
Как опытный технический интервьюер и преподаватель, я часто обнаруживаю, что понимание модульных систем Node.js является краеугольным камнем для любого разработчика JavaScript. Это влияет на все: от того, как вы структурируете свой код, до того, как вы его тестируете.
Давайте разберем модули CommonJS и ES, а также механизмы разрешения и кэширования модулей Node.js.
По своей сути модуль — это автономная единица кода, которую можно повторно использовать в разных частях приложения. Это помогает организовать код, предотвратить загрязнение глобальных переменных и управлять зависимостями. Node.js предоставляет две основные системы модулей: CommonJS (более старая, стандартная) и ES Modules (более новая, стандартная система JavaScript).
CommonJS — это исходная система модулей Node.js по умолчанию. Он был разработан для серверных сред и синхронной загрузки.
module.exports
или его сокращение
exports
.
require()
функция.
require()
модуль, Node.js приостанавливает выполнение текущего файла до тех пор, пока требуемый модуль не будет загружен и оценен.
require()
модули условно, внутри
if
операторе или даже внутри вызова функции. Путь также можно построить динамически.
require
d, он получает копию экспортированного значения во время экспорта. Если исходный модуль позже изменит экспортированное примитивное значение, импортирующий модуль не увидит этого изменения. Для объектов это ссылка на объект, поэтому изменения свойств объекта будут отражены.
__dirname
(текущее имя каталога) и
__filename
(текущее имя файла).
Представьте, что вам нужна конкретная книга. С CommonJS вы как будто физически заходите в библиотеку (
require()
), найдите книгу и верните ее, прежде чем продолжить чтение текущей книги. Вы можете решить, какую книгу взять прямо сейчас, и библиотекарь вручит вам копию (или саму бумажную книгу).
Создадим два файла:
math.js
и
app.js
.
// --- math.js (CommonJS Module) ---
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
// Exporting functionalities
module.exports = {
add: add,
subtract: subtract
};
console.log('math.js module loaded (CommonJS)'); // This runs when the module is first required// --- app.js (CommonJS Consumer) ---
const math = require('./math.js'); // Synchronously loads math.js
console.log('App started (CommonJS)');
console.log('Sum:', math.add(5, 3));
console.log('Difference:', math.subtract(10, 4));
const anotherMath = require('./math.js'); // This will use the cached version, won't re-execute math.js
console.log('Another math instance (CommonJS):', anotherMath.add(1, 1));**Выход при работе
node app.js
:**
math.js module loaded (CommonJS)
App started (CommonJS)
Sum: 8
Difference: 6
Another math instance (CommonJS): 2Уведомление
math.js module loaded (CommonJS)
появляется только один раз, хотя
require('./math.js')
вызывается дважды. Это демонстрирует кэширование.
Модули ES — это официальный стандарт модулей JavaScript, разработанный как для браузеров, так и для Node.js. Их обычно предпочитают для новых проектов Node.js из-за их стандартизированного характера и современных функций.
Node.js рассматривает файлы как ES-модули несколькими способами:
.mjs
расширение**: файлы, заканчивающиеся на
.mjs
всегда рассматриваются как модули ES. 2. **
"type": "module"
в
package.json
**: Если ваш
package.json
файл содержит
"type": "module"
, все
.js
файлы в этом пакете (и его подкаталогах, если это не переопределено
"type": "commonjs"
в суб-
package.json
) рассматриваются как модули ES. 3. Явный импорт: когда модуль CJS использует
import()
(динамический импорт) или скрипт запускается с
node --input-type=module -e 'import ...'
, это рассматривается как ESM.
import
операторы поднимаются (обрабатываются перед выполнением любого кода). Они заранее определяют зависимости, что позволяет проводить статический анализ и потенциально параллельную загрузку. Фактический процесс загрузки не блокируется. Динамический
import()
(вызов функции) полностью асинхронен и возвращает обещание.
import
именованный экспорт (например,
export const counter
), вы получаете «живую привязку» к исходной переменной в модуле экспорта. Если модуль экспорта позже изменит значение
counter
, модуль импорта увидит обновленное значение. Для экспорта по умолчанию это копия значения.
__dirname
/
__filename
**: Они не доступны напрямую. Обычно вы используете
import.meta.url
вместе с Node.js
url
и
path
модули для построения эквивалентных путей.
С модулями ES вы словно передаете в службу доставки список всех книг, которые вам понадобятся для всего сеанса чтения (
import
). Они заранее собирают для вас все книги и доставляют их на ваш стол прежде, чем вы начнете читать. Вы получите последнее издание любой книги, которую запросите.
Убедитесь, что ваш
package.json
содержит
"type": "module"
или используйте
.mjs
расширение.
// --- package.json ---
{
"name": "my-app",
"version": "1.0.0",
"type": "module" // This makes all .js files in this project ES Modules by default
}// --- math.js (модуль ES) ---
экспортировать const add = (a, b) => a + b;
## Итог
Ключевой вывод для интервью: обсудите различия между модулями CommonJS и ES в Node.js. Как Node.js разрешает и кэширует модули и что