Переменная NODE_ENV и её влияние на сборку

Переменная окружения NODE_ENV является одним из наиболее распространённых механизмов управления режимами работы JavaScript-приложений. В экосистеме Node.js она используется для разделения окружений разработки, тестирования и продакшена.

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

Наиболее распространённые значения:

NODE_ENV=development
NODE_ENV=production
NODE_ENV=test

В большинстве проектов используются первые два режима.


Роль NODE_ENV в Parcel

Parcel анализирует переменную окружения и на её основе изменяет стратегию сборки.

Основные различия между режимами:

Возможность development production
Минификация Нет Да
Source Maps Да Обычно да
Оптимизация ресурсов Минимальная Максимальная
Tree Shaking Ограниченно Активно
Скорость сборки Максимальная Ниже
Размер итогового бандла Больше Меньше
Отладочная информация Полная Сокращённая

Фактически значение NODE_ENV определяет, должен ли Parcel сосредоточиться на удобстве разработки или на эффективности итоговой сборки.


Режим разработки

Во время разработки приоритетом является скорость пересборки проекта и удобство отладки.

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

NODE_ENV=development parcel src/index.html

или

parcel serve src/index.html

В этом режиме Parcel:

  • запускает локальный сервер;
  • активирует Hot Module Replacement (HMR);
  • сохраняет подробные карты исходников;
  • не выполняет агрессивные оптимизации;
  • предоставляет максимально читаемые сообщения об ошибках.

Например, код:

function calculatePrice(price) {
    return price * 1.2;
}

console.log(calculatePrice(100));

после сборки остаётся практически в исходном виде, что облегчает поиск ошибок через инструменты разработчика браузера.


Режим production

Продакшен-сборка предназначена для публикации приложения.

Пример:

NODE_ENV=production parcel build src/index.html

или

parcel build src/index.html

При создании продакшен-бандла Parcel выполняет ряд оптимизаций:

  • минификацию JavaScript;
  • минификацию CSS;
  • оптимизацию изображений;
  • удаление неиспользуемого кода;
  • сокращение имён переменных;
  • объединение модулей;
  • сжатие выходных файлов.

Исходный код:

function calculatePrice(price) {
    return price * 1.2;
}

console.log(calculatePrice(100));

может превратиться в:

console.log(1.2*100);

или даже в ещё более компактный вариант после дополнительных оптимизаций.


Как Parcel определяет NODE_ENV

Parcel автоматически устанавливает значение переменной в зависимости от команды.

Для команды:

parcel serve

обычно используется:

NODE_ENV=development

Для команды:

parcel build

используется:

NODE_ENV=production

Поэтому в большинстве случаев явное указание переменной не требуется.

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


Использование NODE_ENV внутри приложения

Переменная окружения может использоваться непосредственно в коде.

Пример:

if (process.env.NODE_ENV === 'development') {
    console.log('Режим разработки');
}

или:

if (process.env.NODE_ENV === 'production') {
    analytics.enable();
}

Во время сборки Parcel подставляет конкретное значение переменной.

Например:

if (process.env.NODE_ENV === 'production') {
    console.log('Analytics enabled');
}

после сборки может быть преобразовано в:

if ('production' === 'production') {
    console.log('Analytics enabled');
}

Это открывает возможность для дальнейших оптимизаций.


Удаление мёртвого кода

Одним из наиболее важных эффектов использования NODE_ENV является механизм Dead Code Elimination.

Рассмотрим пример:

if (process.env.NODE_ENV !== 'production') {
    console.log('Debug information');
}

После подстановки значения:

if ('production' !== 'production') {
    console.log('Debug information');
}

Условие всегда ложно.

Оптимизатор способен удалить весь блок:

// код удалён

В результате:

  • уменьшается размер бандла;
  • исключаются ненужные вычисления;
  • повышается производительность приложения.

NODE_ENV и Tree Shaking

Tree Shaking — механизм удаления неиспользуемых экспортов из модулей.

Пример:

export function sum(a, b) {
    return a + b;
}

export function debugLog(message) {
    console.log(message);
}

Использование:

import { sum } from './utils';

console.log(sum(2, 3));

В production-сборке Parcel способен исключить функцию:

debugLog()

поскольку она нигде не используется.

Значение NODE_ENV=production активирует наиболее агрессивные алгоритмы подобных оптимизаций.


Условное подключение инструментов разработки

Часто в проекте присутствуют библиотеки, необходимые исключительно разработчикам.

Например:

if (process.env.NODE_ENV === 'development') {
    import('./debug-tools');
}

Модуль:

debug-tools.js

может содержать:

export function startInspector() {
    console.log('Inspector started');
}

В production-сборке такой код полностью исключается.

Подобный подход позволяет не загружать пользователям инструменты диагностики.


Настройка через package.json

Чаще всего значение NODE_ENV задаётся в npm-скриптах.

Пример:

{
  "scripts": {
    "dev": "NODE_ENV=development parcel serve src/index.html",
    "build": "NODE_ENV=production parcel build src/index.html"
  }
}

Запуск:

npm run dev

активирует режим разработки.

Запуск:

npm run build

создаёт оптимизированную сборку.


Кроссплатформенная установка переменной

Команда:

NODE_ENV=production parcel build

работает в Linux и macOS.

В Windows используется другой синтаксис:

set NODE_ENV=production && parcel build

Для создания переносимых скриптов применяется пакет cross-env.

Установка:

npm install --save-dev cross-env

Использование:

{
  "scripts": {
    "build": "cross-env NODE_ENV=production parcel build src/index.html"
  }
}

Теперь один и тот же скрипт работает во всех операционных системах.


Влияние на React

React активно использует значение NODE_ENV.

Пример:

if (__DEV__) {
    warning(...);
}

Во время production-сборки React отключает:

  • предупреждения;
  • проверки корректности пропсов;
  • диагностические сообщения;
  • дополнительные проверки компонентов.

Поэтому размер production-версии React существенно меньше development-версии.

Parcel автоматически обеспечивает передачу корректного значения среды в React-приложение.


Влияние на сторонние библиотеки

Многие популярные библиотеки ориентируются на значение NODE_ENV.

Примеры:

  • React;
  • Redux;
  • MobX;
  • Vue;
  • Preact;
  • Apollo Client;
  • Zustand;
  • Sentry SDK.

Типичная конструкция выглядит следующим образом:

if (process.env.NODE_ENV !== 'production') {
    console.warn('Deprecated API');
}

В production-режиме подобный код удаляется оптимизатором.


Использование пользовательских режимов

Технически возможно задавать любые значения:

NODE_ENV=staging

или

NODE_ENV=qa

Проверка:

if (process.env.NODE_ENV === 'staging') {
    console.log('Staging mode');
}

Однако большинство инструментов ориентируется исключительно на значения:

development
production
test

Поэтому нестандартные режимы следует использовать осторожно.

Для хранения дополнительных параметров чаще создаются отдельные переменные окружения:

API_URL=https://staging.example.com
FEATURE_X=true

NODE_ENV и тестирование

При запуске тестов обычно используется:

NODE_ENV=test

Такой режим позволяет:

  • отключать аналитические системы;
  • не выполнять продакшен-оптимизации;
  • подменять внешние сервисы;
  • использовать тестовые базы данных.

Пример:

if (process.env.NODE_ENV === 'test') {
    mockServer.start();
}

Подобный подход делает тесты независимыми от реальной инфраструктуры.


Проверка текущего значения

Получить текущее значение можно следующим образом:

console.log(process.env.NODE_ENV);

Результат:

development

или:

production

Это полезно при диагностике проблем со сборкой и настройкой окружения.


Типичные ошибки

Использование неправильного значения

Неверно:

if (process.env.NODE_ENV === 'prod')

Правильно:

if (process.env.NODE_ENV === 'production')

Большинство библиотек ожидает строго определённые строки.

Жёсткое переключение логики

Нежелательно:

if (process.env.NODE_ENV === 'production') {
    apiUrl = 'https://api.example.com';
} else {
    apiUrl = 'http://localhost:3000';
}

Лучше использовать отдельные переменные:

const apiUrl = process.env.API_URL;

Хранение конфигурации только через NODE_ENV

Плохая практика:

if (process.env.NODE_ENV === 'production') {
    featureEnabled = true;
}

Более гибкий вариант:

featureEnabled = process.env.FEATURE_ENABLED === 'true';

NODE_ENV должен определять тип окружения, а не содержать всю конфигурацию приложения.


Практическая схема использования

Для большинства проектов применяется следующая структура:

development
├─ подробные логи
├─ HMR
├─ инструменты отладки
└─ source maps

test
├─ мок-сервисы
├─ тестовые данные
└─ отключённая аналитика

production
├─ минификация
├─ tree shaking
├─ удаление debug-кода
├─ оптимизация ресурсов
└─ максимальная производительность

В сочетании с механизмами оптимизации Parcel переменная NODE_ENV становится одним из ключевых инструментов управления процессом сборки, позволяя получать быстрый цикл разработки и максимально эффективный продакшен-бандл из одной и той же кодовой базы.