Node.js таргет

В Parcel система таргетов определяет, под какую среду выполняется сборка приложения. Один из ключевых режимов — Node.js-таргет, который ориентирован на выполнение кода в среде Node.js без браузерного окружения, DOM и Web API. В этом режиме сборщик перестраивает граф модулей, учитывает встроенные возможности Node.js и исключает типичные браузерные преобразования.

Node.js таргет задаёт семантику сборки, при которой выходной код предполагается запускать в серверной среде. Это влияет на:

  • формат модулей (CommonJS или ESM в зависимости от конфигурации),
  • обработку встроенных Node.js API,
  • исключение браузерных полифилов,
  • работу с внешними зависимостями,
  • стратегию бандлинга (или его частичное отключение).

В отличие от браузерного таргета, где основной целью является оптимизация загрузки в сети и совместимость с браузерами, Node.js таргет ориентирован на выполнение в файловой системе и серверном рантайме.

Конфигурация targets в Parcel

В Parcel v2 таргеты определяются через поле targets в package.json. Это позволяет описывать несколько выходных сборок для одного проекта.

{
  "name": "server-app",
  "source": "src/index.js",
  "targets": {
    "node": {
      "context": "node",
      "outputFormat": "commonjs",
      "distDir": "dist/node",
      "engines": {
        "node": ">=18"
      }
    }
  }
}

Ключевые параметры:

  • context — задаёт среду выполнения (node)
  • outputFormat — формат модулей (CommonJS или ESModules)
  • distDir — директория для результата сборки
  • engines.node — минимальная версия Node.js

Parcel использует эту информацию для выбора трансформаций и стратегии упаковки.

Отличия Node.js таргета от браузерного

Node.js таргет принципиально отличается по нескольким направлениям.

Отсутствие DOM и Web API

В Node.js нет:

  • window
  • document
  • localStorage
  • fetch (в старых версиях Node)

Поэтому Parcel:

  • не включает DOM-полифилы,
  • не подменяет глобальные браузерные объекты,
  • не добавляет лишние runtime-библиотеки.

Использование встроенных модулей Node.js

Node.js предоставляет встроенные модули:

  • fs
  • path
  • http
  • crypto

Parcel при сборке:

  • не бандлит встроенные модули,
  • оставляет require("fs") или import "fs" без изменений,
  • маркирует их как external-зависимости.

Работа с зависимостями

В Node.js таргете Parcel по умолчанию:

  • не инлайнит все зависимости в один файл,
  • может оставлять структуру node_modules нетронутой,
  • оптимизирует только пользовательский код.

Это важно для серверных приложений, где бандлинг всего графа может быть избыточным.

Модульные системы: CommonJS и ESM

Parcel поддерживает оба основных формата:

  • CommonJS (require, module.exports)
  • ES Modules (import, export)

В Node.js таргете выбор формата влияет на результат:

CommonJS выход

{
  "targets": {
    "node": {
      "outputFormat": "commonjs"
    }
  }
}

Результат:

const express = require("express");

module.exports = function app() {
  return express();
};

ESM выход

{
  "targets": {
    "node": {
      "outputFormat": "esmodule"
    }
  }
}

Результат:

import express from "express";

export function app() {
  return express();
}

Node.js таргет учитывает также "type": "module" в package.json, что влияет на интерпретацию файлов.

External dependencies и стратегия бандлинга

В серверной среде часто требуется сохранить структуру зависимостей. Parcel в Node.js таргете применяет особую стратегию:

  • зависимости из node_modules часто помечаются как external,
  • код приложения компилируется, но не всегда объединяется в один файл,
  • сохраняется возможность использования нативного require.

Пример:

import lodash from "lodash";
import { readFile } from "fs";

После сборки:

  • lodash остаётся внешним пакетом,
  • fs остаётся встроенным модулем Node.js,
  • пользовательский код трансформируется и оптимизируется.

Полифилы и их отключение

В браузерных сборках Parcel может добавлять полифилы для:

  • process
  • Buffer
  • path
  • crypto

В Node.js таргете это поведение отключается, так как среда уже предоставляет эти API.

Это уменьшает:

  • размер итоговой сборки,
  • количество runtime-обёрток,
  • вероятность конфликтов версий полифилов.

Работа с переменными окружения

Node.js таргет активно использует process.env без дополнительных преобразований.

const port = process.env.PORT || 3000;

Parcel не заменяет такие выражения автоматически, если не включена отдельная оптимизация через переменные окружения сборщика.

Tree-shaking в Node.js таргете

Хотя Node.js традиционно менее агрессивен к оптимизациям, Parcel всё равно применяет tree-shaking там, где это возможно:

  • удаляются неиспользуемые экспорты,
  • исключается мёртвый код,
  • оптимизируются чистые функции.

Однако уровень агрессии ниже, чем в браузерных сборках, поскольку:

  • динамический require сложнее анализировать,
  • серверные приложения часто используют динамическую загрузку модулей.

Source maps и отладка

Node.js таргет активно поддерживает source maps:

  • упрощает отладку серверного кода,
  • сохраняет оригинальную структуру файлов,
  • позволяет использовать дебаггер Node.js без потери контекста.

Пример запуска:

node --enable-source-maps dist/node/index.js

Parcel генерирует .map файлы автоматически при включённой конфигурации режима разработки или production.

Гибридные проекты

Parcel позволяет комбинировать таргеты:

{
  "targets": {
    "browser": {
      "context": "browser"
    },
    "node": {
      "context": "node"
    }
  }
}

Это используется в архитектурах:

  • SSR (server-side rendering),
  • universal applications,
  • shared code между сервером и клиентом.

Общий код может компилироваться с учётом обеих сред, но с разными условиями выполнения:

if (typeof window !== "undefined") {
  console.log("browser");
} else {
  console.log("node");
}

Особенности работы с файловой системой

В Node.js таргете доступ к файловой системе остаётся нативным:

import fs from "fs";

const data = fs.readFileSync("./config.json", "utf-8");

Parcel не вмешивается в такие вызовы и не пытается их абстрагировать, так как они являются частью runtime-среды.

Ограничения Node.js таргета

Несмотря на гибкость, существуют ограничения:

  • невозможность использовать браузерные API без полифилов,
  • ограниченная оптимизация динамических импортов,
  • зависимость от структуры node_modules,
  • различия между версиями Node.js, влияющие на транспиляцию.

Эти особенности требуют точной настройки engines и понимания целевой среды выполнения.