Миграция с React на Preact

Основные отличия Preact от React

Preact — это легковесная альтернатива React, сохраняющая совместимость с его основными концепциями: виртуальный DOM, JSX, компонентная структура, хуки. Основное отличие заключается в размере библиотеки: Preact весит около 3 КБ, что значительно уменьшает время загрузки приложений и улучшает производительность, особенно на мобильных устройствах и при медленном соединении.

Другие ключевые различия:

  • API хуков полностью совместимо, но некоторые специфические хуки React, такие как useLayoutEffect, могут вести себя иначе из-за различий в жизненном цикле Preact.
  • Context API работает аналогично, однако есть нюансы с оптимизацией рендеринга, которые могут потребовать переработки некоторых компонентов.
  • Refs и forwardRef поддерживаются, но внутренние механизмы обновления компонента проще, что иногда меняет поведение сложных рефов.
  • Preact не поддерживает PropTypes и встроенные проверки типов, это нужно учитывать при миграции больших проектов.

Настройка проекта для миграции

  1. Установка Preact:
npm install preact preact-compat
  1. Конфигурация сборщика (например, Webpack или Vite) для замены React на Preact:
// webpack.config.js
resolve: {
  alias: {
    'react': 'preact/compat',
    'react-dom/test-utils': 'preact/test-utils',
    'react-dom': 'preact/compat',
  },
}

В Vite замена выполняется через плагин @preact/preset-vite:

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

export default defineConfig({
  plugins: [preact()],
});
  1. Проверка зависимости хуков и библиотек: многие сторонние библиотеки React будут работать с Preact через preact/compat, но нужно убедиться, что используемые функции React поддерживаются.

Работа с компонентами

Preact использует функциональные компоненты и поддерживает хуки так же, как React:

import { h } from 'preact';
import { useState } from 'preact/hooks';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>{count}</p>
      <button onCl ick={() => setCount(count + 1)}>Увеличить</button>
    </div>
  );
}

Особенности при миграции:

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

Хуки и управление состоянием

Preact поддерживает большинство стандартных хуков React:

  • useState, useEffect, useContext, useReducer, useRef, useMemo, useCallback.
  • Отличия проявляются в порядке вызова эффектов и оптимизации рендеринга, особенно при использовании useLayoutEffect в браузерах с высокой задержкой.

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

import { createContext } from 'preact';
import { useContext } from 'preact/hooks';

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Кнопка</button>;
}

Оптимизация рендеринга

Preact автоматически минимизирует количество обновлений DOM, но для крупных проектов рекомендуется:

  • Использовать memo для компонентов с неизменяемыми пропсами.
  • Разбивать приложение на мелкие компоненты для снижения объема повторных рендеров.
  • Проверять использование useEffect и useLayoutEffect для предотвращения лишних вызовов.

Работа со сторонними библиотеками

С Preact совместимы большинство популярных React-библиотек через preact/compat. Однако:

  • Некоторые библиотеки, завязанные на внутренние API React (например, нестабильные экспериментальные хуки), могут потребовать замены или переписывания.
  • Проверка работы тестов на Jest или Cypress особенно важна, так как поведение act() в Preact отличается от React.

Особенности маршрутизации и состояния

  • Preact Router: легковесная замена React Router, синтаксис прост и удобен:
import { h } from 'preact';
import { Router, Route } from 'preact-router';
import Home from './Home';
import About from './About';

function App() {
  return (
    <Router>
      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
    </Router>
  );
}
  • Для управления состоянием можно использовать Redux, Zustand, или Context API, но нужно убедиться в совместимости с Preact через preact/compat.

Тестирование и отладка

  • Jest и Testing Library поддерживают Preact с preact/compat.
  • DevTools: Preact DevTools доступен как расширение Chrome, позволяя инспектировать дерево компонентов и состояние.

Основные шаги миграции

  1. Установить preact и preact/compat.
  2. Настроить сборщик для alias React → Preact.
  3. Проверить использование хуков, контекста и сторонних библиотек.
  4. Переписать или оптимизировать компоненты с классами на функциональные.
  5. Провести тестирование приложения, включая рендеринг и пользовательский интерфейс.
  6. Оптимизировать рендеринг через memo и разбивку компонентов.

Preact позволяет значительно уменьшить размер бандла и ускорить загрузку приложения, сохраняя привычную структуру React-компонентов и работу с хуками. Миграция требует внимательного анализа сторонних библиотек и компонентов с классами, но при соблюдении правил совместимости процесс проходит относительно гладко.