Preact: алиасы и оптимизация

В экосистеме современных фронтенд-сборщиков одним из ключевых механизмов оптимизации является подмена тяжёлых зависимостей на более лёгкие аналоги без изменения прикладного кода. Parcel предоставляет встроенную поддержку алиасов модулей, что позволяет заменить react и react-dom на preact и preact/compat на уровне сборки.

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

import React from "react";
import ReactDOM from "react-dom";

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

Механизм алиасов в Parcel

Parcel поддерживает поле alias в package.json, которое позволяет переопределять пути модулей:

{
  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat",
    "react/jsx-runtime": "preact/jsx-runtime"
  }
}

Такое сопоставление делает возможной прозрачную замену React на Preact без модификации исходного кода компонентов.

Ключевой компонент здесь — preact/compat, который реализует слой совместимости API React, включая хуки, контекст и базовые методы жизненного цикла.

Совместимость через preact/compat

Библиотека preact/compat выступает адаптером между React API и ядром Preact. Она обеспечивает:

  • поддержку useState, useEffect, useMemo, useCallback
  • работу контекста через createContext
  • совместимость с большинством React-компонентов
  • поддержку JSX-runtime нового формата

В результате приложение, написанное под React 17–18, в большинстве случаев может работать без изменений.

Влияние замены React на Preact на размер бандла

Одной из основных причин использования Preact является значительное уменьшение размера итогового JavaScript-бандла.

React и ReactDOM вместе могут занимать десятки килобайт даже в минифицированном виде, тогда как Preact core и compat-слой обычно существенно легче.

Parcel при сборке выполняет:

  • tree-shaking неиспользуемых частей
  • минификацию через Terser или SWC (в зависимости от конфигурации)
  • дедупликацию зависимостей

В комбинации с Preact это даёт дополнительный выигрыш, так как библиотека изначально компактнее и менее многословна по внутренней реализации.

Настройка alias через Parcel v2

Parcel v2 использует декларативный подход к конфигурации. Помимо package.json, алиасы могут быть определены через .parcelrc или через поле alias.

Пример конфигурации для проекта:

{
  "name": "app",
  "dependencies": {
    "preact": "^10.0.0"
  },
  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat",
    "react/jsx-runtime": "preact/jsx-runtime"
  }
}

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

JSX runtime и современная трансформация

Современные версии React используют новый JSX runtime, который больше не требует явного импорта React в каждом файле. Однако при переходе на Preact важно учитывать соответствие runtime.

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

{
  "alias": {
    "react/jsx-runtime": "preact/jsx-runtime",
    "react/jsx-dev-runtime": "preact/jsx-dev-runtime"
  }
}

Это позволяет сохранить корректную трансформацию JSX без дополнительных полифиллов.

Parcel автоматически подхватывает эти алиасы и направляет трансформированный код в нужный runtime.

Оптимизация времени сборки в Parcel

Использование Preact косвенно влияет и на скорость сборки.

Parcel применяет параллельную обработку модулей, и более лёгкие зависимости уменьшают:

  • время анализа графа зависимостей
  • количество обрабатываемых AST-узлов
  • нагрузку на минификатор

Дополнительно оптимизация достигается через:

Кэширование

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

Инкрементальная сборка

Изменения в коде пересобираются локально без полной перестройки бандла.

Code splitting

Parcel автоматически разбивает код на чанки:

const Page = import("./Page");

Это позволяет загружать Preact-приложение по частям, снижая начальную нагрузку.

Уменьшение runtime-издержек

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

Preact отличается более лёгкой виртуальной DOM-реализацией, что влияет на:

  • скорость reconciliation
  • потребление памяти
  • количество аллокаций объектов

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

Работа с зависимостями сторонних библиотек

При замене React на Preact основной риск связан с несовместимостью библиотек, которые жёстко завязаны на React internals.

Parcel позволяет локально переопределять такие зависимости:

{
  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat"
  }
}

Однако в сложных случаях требуется точечная настройка:

  • исключение проблемных пакетов через external
  • использование условных алиасов для отдельных модулей
  • ручная проверка peerDependencies

Tree shaking и устранение мёртвого кода

Parcel выполняет статический анализ импортов и удаляет неиспользуемые части модулей. При использовании Preact эффект усиливается за счёт меньшего числа экспортов.

Пример:

import { useState } from "react";

После алиасинга становится:

import { useState } from "preact/hooks";

Это уменьшает глубину зависимостей и упрощает граф модулей.

Производственная сборка и минификация

В production-режиме Parcel выполняет дополнительные оптимизации:

  • удаление dev-only кода
  • инлайн-константы
  • сокращение идентификаторов
  • агрессивная минификация

При использовании Preact итоговый результат становится ещё более компактным, поскольку базовая библиотека изначально менее громоздкая.

Сопоставление архитектур React и Preact в контексте Parcel

React ориентирован на расширяемую экосистему и включает множество внутренних абстракций. Preact стремится к минимализму и совместимости.

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

Ключевые различия в контексте сборки:

  • React требует больше runtime-кода
  • Preact снижает количество зависимостей
  • Parcel одинаково эффективно обрабатывает оба варианта через единый граф модулей

Ограничения и тонкости алиасинга

Несмотря на прозрачность замены, существуют технические нюансы:

  • некоторые React-специфичные API могут отсутствовать или вести себя иначе
  • библиотеки с прямыми импортами react-dom/client могут требовать дополнительных алиасов
  • SSR-решения требуют отдельной настройки рендеринга

Parcel не решает эти ограничения автоматически, но предоставляет инфраструктуру для точечной корректировки резолвинга модулей.

Оптимизация структуры проекта при использовании Preact

Эффективность связки Parcel + Preact увеличивается при соблюдении архитектурных принципов:

  • минимизация глобальных зависимостей
  • использование функциональных компонентов
  • отказ от тяжёлых HOC-цепочек
  • переход на локальное состояние через хуки
  • разделение кода по feature-based структуре

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