Preact/compat для совместимости

Preact/compat — это специальный модуль, обеспечивающий совместимость Preact с экосистемой React. Он позволяет использовать большинство библиотек и компонентов, разработанных для React, без изменения исходного кода. Основная идея заключается в том, чтобы Preact предоставлял API, идентичное React, включая React.createElement, React.Component и ReactDOM.render.

Установка и подключение

Для работы с Preact/compat необходимо установить пакет:

npm install preact preact/compat

После этого настройка проекта зависит от сборщика. В случае использования Webpack или Vite часто применяется alias, чтобы при импорте React автоматически использовать Preact:

// webpack.config.js
module.exports = {
  resolve: {
    alias: {
      'react': 'preact/compat',
      'react-dom': 'preact/compat'
    }
  }
};

Для Vite:

// vite.config.js
import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';

export default defineConfig({
  plugins: [preact()],
  resolve: {
    alias: {
      'react': 'preact/compat',
      'react-dom': 'preact/compat'
    }
  }
});

После этого любой код, использующий import React from 'react', будет работать с Preact.

Основные возможности

Preact/compat реализует почти все основные функции React:

  • JSX и React.createElement
  • Классовые и функциональные компоненты
  • Hooks (useState, useEffect, useRef и др.)
  • Context API (createContext, useContext)
  • Forward refs и memo

Многие сторонние библиотеки, рассчитанные на React, такие как React Router, Redux или Material-UI, могут работать без изменений благодаря этому модулю.

Особенности использования

  1. Размер библиотеки: Preact существенно меньше React. Использование preact/compat добавляет немного объема, но все равно результат остается легче полноценного React.

  2. Не все функции React: Некоторые малоиспользуемые или экспериментальные API React могут не поддерживаться. Например, старые методы жизненного цикла (deprecated в React 17+) могут работать иначе.

  3. Функции рендеринга: В preact/compat доступен метод ReactDOM.render, который на самом деле является оболочкой над preact.render. Все привычные вызовы остаются корректными.

  4. Portals и StrictMode: Поддержка ReactDOM.createPortal есть, но StrictMode работает частично, так как Preact не реализует все проверки React.

Миграция существующих проектов

Для перевода проекта с React на Preact/compat достаточно:

  1. Установить preact и preact/compat.
  2. Настроить alias для сборщика.
  3. Проверить работу сторонних библиотек. Большинство компонентов будут работать без изменений.
  4. При необходимости заменить специфичные React-фичи на аналоги Preact.

Примеры кода

Функциональный компонент с хуками:

import React, { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => setCount(c => c + 1), 1000);
    return () => clearInterval(interval);
  }, []);

  return <h1>{count}</h1>;
}

export default Counter;

Код полностью совместим с Preact при использовании preact/compat.

Классовый компонент:

import React, { Component } from 'react';

class Timer extends Component {
  state = { seconds: 0 };

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState({ seconds: this.state.seconds + 1 });
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <div>Прошло {this.state.seconds} секунд</div>;
  }
}

export default Timer;

Ограничения и нюансы

  • Стилизация: Preact не поддерживает все внутренние оптимизации React, связанные с синтетическими событиями. Большинство библиотек учитывает это, но редкие кейсы могут потребовать ручной доработки.
  • Фрагменты: React.Fragment полностью поддерживается, но JSX сокращение <>...</> также работает.
  • StrictMode и Concurrent Mode: Preact частично поддерживает StrictMode; Concurrent Mode пока недоступен.

Оптимизация производительности

Даже при использовании preact/compat сохраняются преимущества Preact:

  • Меньший размер бандла.
  • Быстрый рендеринг и обновления DOM.
  • Более простое управление памятью и событиями.

Для крупных проектов рекомендуется:

  • Использовать memo для оптимизации повторного рендеринга компонентов.
  • Избегать избыточного использования тяжелых библиотек React, если есть их Preact-ориентированные аналоги.
  • Использовать preact/debug для локальной разработки и отладки, чтобы увидеть предупреждения и ошибки.