Безопасное хранение данных

Preact — это лёгкий и высокопроизводительный JavaScript-фреймворк для создания интерфейсов, совместимый с React, но существенно меньше по размеру и быстрее в работе с DOM. Его основной принцип заключается в минимизации объёма кода при сохранении возможности использовать знакомый API React, включая компоненты, хуки и JSX.

Преимущества Preact:

  • Минимальный размер — около 3 кБ после сжатия, что критично для мобильных приложений и ленивой загрузки.
  • Совместимость с React через пакет preact/compat, что позволяет переносить существующие проекты.
  • Высокая скорость рендеринга и обновления DOM благодаря собственной реализации виртуального DOM.
  • Простая интеграция с современными сборщиками, такими как Vite и Webpack.

Компоненты и JSX

Компоненты Preact бывают двух типов: функциональные и классовые. Функциональные компоненты — основной современный подход:

import { h } from 'preact';

function Button({ label, onClick }) {
  return <button onCl ick={onClick}>{label}</button>;
}

JSX — синтаксис, позволяющий писать HTML-подобный код прямо в JavaScript. Preact автоматически компилирует JSX в вызовы h():

const element = <div className="container">Пример</div>;
// Компилируется в
const element = h('div', { className: 'container' }, 'Пример');

Ключевой момент — правильное использование className вместо class, чтобы избежать конфликтов с зарезервированными словами JavaScript.

Работа с состоянием

Preact использует хуки, аналогичные React. Основной хук — useState:

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:

  • Обновления состояния выполняются асинхронно и оптимизированы для минимального числа перерисовок.
  • Поддержка useEffect для побочных эффектов и useRef для прямого взаимодействия с DOM.

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

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

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 предлагает лёгкий роутер preact-router:

import Router from 'preact-router';
import Home from './Home';
import About from './About';

function App() {
  return (
    <Router>
      <Home path="/" />
      <About path="/about" />
    </Router>
  );
}

Особенности:

  • Поддержка динамических маршрутов.
  • Лёгкая интеграция с lazy-loading компонентов для оптимизации загрузки страниц.

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

Preact изначально оптимизирован, но дополнительные меры включают:

  • Lazy-loading компонентов через динамический импорт:
import { lazy, Suspense } from 'preact/compat';

const LazyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Загрузка...</div>}>
      <LazyComponent />
    </Suspense>
  );
}
  • Использование shouldComponentUpdate или мемоизации memo для предотвращения ненужных перерисовок.
  • Минимизация состояния и использование useReducer для сложной логики.

Безопасное хранение данных

Хранение чувствительных данных в фронтенде требует особого внимания. Основные принципы:

  1. Не хранить секреты на клиенте. Любой код, выполняемый на стороне пользователя, потенциально доступен через DevTools. API-ключи и пароли должны храниться на сервере.

  2. Использовать безопасные хранилища браузера. Для пользовательских настроек и токенов применяются:

    • localStorage — хранение данных между сессиями, но уязвимо для XSS.
    • sessionStorage — временное хранение в пределах вкладки.
    • IndexedDB — для больших объемов данных.

    Рекомендуется шифровать данные перед сохранением:

import CryptoJS from 'crypto-js';

const secret = 'данные';
const encrypted = CryptoJS.AES.encrypt(secret, 'ключ').toString();
localStorage.setItem('secretData', encrypted);

// Для получения
const bytes = CryptoJS.AES.decrypt(localStorage.getItem('secretData'), 'ключ');
const originalData = bytes.toString(CryptoJS.enc.Utf8);
  1. Регулярная очистка хранилища. Удаление устаревших токенов и данных снижает риск компрометации.
  2. Использование HttpOnly cookies для токенов авторизации. Такой способ защищает от XSS, так как данные недоступны через JavaScript.
  3. Валидация и фильтрация данных. Любые данные, полученные с фронтенда, должны быть проверены на сервере перед использованием или сохранением.

Интеграция с внешними API

Preact легко интегрируется с REST и GraphQL. Для работы с API используют fetch или библиотеки вроде axios. Пример безопасного запроса с токеном авторизации:

import { useEffect, useState } from 'preact/hooks';

function UserProfile() {
  const [profile, setProfile] = useState(null);

  useEffect(() => {
    const token = localStorage.getItem('authToken');

    fetch('https://api.example.com/profile', {
      headers: { 'Authorization': `Bearer ${token}` },
    })
      .then(res => res.json())
      .then(data => setProfile(data))
      .catch(err => console.error(err));
  }, []);

  return profile ? <div>{profile.name}</div> : <div>Загрузка...</div>;
}

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

Для тестирования компонентов применяются @testing-library/preact и Jest. Основные подходы:

  • Тестирование визуального рендеринга.
  • Проверка работы хуков и состояния.
  • Проверка интеграции с API через мок-сервисы.

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