Нативные модули представляют собой бинарные расширения Node.js,
реализованные на C или C++, и загружаемые через механизм
require. Такие модули имеют расширение .node и
компилируются под конкретную платформу, архитектуру процессора и версию
Node.js. Их ключевая особенность заключается в выполнении кода вне V8, с
доступом к системным API и высокой производительностью.
Типичный пример — библиотеки для работы с базами данных, криптографией, обработкой изображений и файловой системой. В отличие от чистого JavaScript, нативные модули требуют сборки и наличия подходящей бинарной версии для целевой среды выполнения.
Parcel рассматривает нативные модули как особый класс зависимостей, находящийся на границе между JavaScript-кодом и внешними бинарными артефактами. Их обработка зависит от целевой платформы сборки:
Parcel не пытается транспилировать .node файлы,
поскольку они не являются текстовым исходным кодом. Вместо этого
применяется стратегия разрешения и копирования артефактов.
В процессе анализа зависимостей Parcel использует резолвер, который определяет тип модуля по нескольким признакам:
.node)binding.gypnode-gyp-совместимых пакетовprebuild или
prebuildify структуреПри обнаружении нативного модуля он помечается как external binary dependency, что исключает его из стандартного графа трансформаций JavaScript.
Нативные модули часто поставляются в виде набора бинарников под разные платформы:
/build/Release/module.node
/prebuilds/linux-x64/node.napi.node
/prebuilds/darwin-arm64/node.napi.node
Parcel при сборке учитывает параметры окружения:
process.platformprocess.archАлгоритм выбора бинарника основывается на приоритетах:
Если ни один вариант не подходит, модуль считается недоступным для целевой платформы.
Современные пакеты используют поле exports для
определения условий загрузки:
{
"exports": {
"node": {
"require": "./index.node.js"
},
"default": "./index.js"
}
}
Parcel учитывает условия экспорта:
node — при сборке под Node.jsbrowser — при клиентской сборкеimport / require — в зависимости от типа
модуляdefault — fallbackДля нативных модулей часто применяется ветка node,
которая возвращает обёртку над бинарным файлом.
.node файловФайлы .node не включаются в JavaScript bundle. Вместо
этого Parcel:
require()В результате итоговый код в Node.js сохраняет семантику:
const native = require('./build/Release/addon.node');
Parcel гарантирует, что путь указывает на реальный файл в итоговом
dist.
В клиентской среде нативные модули недоступны. При обнаружении
.node зависимостей Parcel применяет одну из стратегий:
Выбор стратегии зависит от конфигурации и режима сборки. Типичный случай — выбрасывание ошибки на этапе бандлинга:
Нативный модуль не может быть использован в браузерной среде
Это предотвращает попадание неработоспособного кода в клиентский bundle.
Многие нативные пакеты объявляются как
optionalDependencies, поскольку их установка может быть
невозможна на некоторых платформах:
{
"optionalDependencies": {
"fsevents": "^2.3.0"
}
}
Parcel учитывает этот механизм и не требует обязательного наличия всех бинарных зависимостей при сборке. Отсутствующие optional-модули исключаются без остановки процесса.
Современный подход к нативным модулям опирается на N-API, обеспечивающий стабильный ABI между версиями Node.js. Такие модули:
Parcel рассматривает N-API как приоритетный формат, поскольку он снижает необходимость сложной платформенной логики.
Если пакет не содержит предсобранных бинарников, используется
node-gyp. Parcel не выполняет компиляцию самостоятельно, но
учитывает результат:
build/.nodeТаким образом, процесс сборки нативного кода остаётся вне зоны ответственности Parcel.
WebAssembly часто используется как кроссплатформенная замена нативных расширений. Parcel поддерживает WASM как первоклассный asset:
.wasm файлов как модулейWebAssembly.instantiateВ отличие от .node файлов, WASM работает как в Node.js,
так и в браузере, что снижает необходимость ветвления зависимостей.
Некоторые нативные модули используются в контексте
worker_threads. Parcel учитывает это при построении графа
зависимостей:
.node сохраняются относительно worker entry
pointЭто важно для библиотек, выполняющих тяжёлые вычисления вне main thread.
Нативные модули редко изменяются в процессе разработки, поэтому Parcel применяет агрессивное кэширование:
.node файлов не хэшируется как текстЭто снижает стоимость пересборки больших проектов с тяжёлыми бинарными зависимостями.
При работе с нативными модулями возникают специфические классы ошибок:
x64 vs
arm64)Parcel фиксирует часть этих проблем на этапе сборки, но runtime-ошибки остаются возможными, особенно в динамически загружаемых модулях.
Для обеспечения корректной работы нативных модулей применяются следующие подходы:
exportsParcel в этом контексте выступает как слой маршрутизации и упаковки, не вмешиваясь в бинарную природу зависимостей.