Реализация островков React в статических веб-приложениях

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

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

В этом руководстве мы шаг за шагом рассмотрим внедрение React Islands на примере реального мира. Вы узнаете, как:

  • Добавление компонентов React в приложение vanilla JavaScript
  • Передача данных между React и вашим существующим кодом
  • Осуществлять государственное управление по всему миру
  • Избегайте распространенных ошибок и подводного камня

Когда вам следует использовать React Islands?

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

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

Хорошее

Разделы React позволяют постепенно модернизировать ваше приложение, избегая необходимости полного переписывания. Вы можете внедрять React поэтапно, уделяя особое внимание тем областям, где это необходимо, оставляя при этом остальную часть приложения нетронутой. Это сводит к минимуму риски и сбои в работе.

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

Что касается гидратации, давайте рассмотрим некоторые моменты в контексте. Традиционно React hydration работает путем рендеринга всей страницы сервером. Затем клиент загружает React и повторно гидратирует всю страницу, делая все компоненты интерактивными одновременно. В отличие от этого, "Архитектура острова" изменяет этот процесс, сохраняя большую часть страницы статичной. Гидратации подвергаются только определенные компоненты, и гидратация происходит независимо для каждого острова.

Наконец, эти островки помогают в SEO, поскольку статический контент легко доступен для поиска поисковыми системами.

Не очень хорошие Давайте поговорим о проблемах, с которыми вы столкнетесь при использовании React Islands. Несмотря на то, что React Islands является мощным инструментом, есть несколько серьезных недостатков, на которые следует обратить внимание.

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

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

Изменения в макете могут ухудшить восприятие пользователем, когда ваши островки будут перегружены и изменят размер. Ваш статический HTML-код может отображаться не так, как в конечном интерактивном состоянии, что приведет к скачиванию содержимого во время загрузки.

Измерение производительности становится более тонким - традиционные показатели не дают полной картины, поскольку разные части вашей страницы становятся интерактивными в разное время.

Идеальные варианты использования

  • Насыщенные контентом сайты с минимальной интерактивностью
  • Страницы, на которых большая часть контента статична
  • Сценарии, в которых производительность имеет решающее значение
  • Требования к прогрессивному совершенствованию

Проблемы, возникающие при внедрении в реальных условиях

В этой статье из The Guardian они рассказывают о своем подходе к интеграции React Islands и о некоторых проблемах, с которыми они столкнулись в ходе этого процесса. Давайте выделим некоторые ключевые выводы и инсайты из их опыта:

1. Опыт разработчика имеет значение В то время как первоначальные внедрения часто фокусируются на показателях производительности, опыт Guardian показывает, что опыт разработчиков имеет решающее значение для долгосрочного успеха. При втором внедрении были достигнуты цели по производительности, но поддерживать их было сложно:

  • Добавление новых островов потребовало изменений в нескольких местах
  • Разработчики могут непреднамеренно ввести неиспользуемый JavaScript
  • Частые изменения кода вновь привели к снижению производительности

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

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

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

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

3. Рекомендации по извлечению данных Часто нескольким островкам требуются одни и те же данные, что может привести к дублированию вызовов API. Решения этой проблемы включают:

  • Использование библиотек для извлечения данных со встроенной дедупликацией (например, SWR)
  • Допускать некоторое дублирование простых операций (например, чтение файлов cookie)
  • Тщательное планирование потоков данных и стратегий кэширования

Отправная точка: устаревшее приложение

Давайте начнем с простой страницы каталога товаров. Вот наша первоначальная версия на vanilla JavaScript:

<body>
    <div class="container">
        <h1>Product Catalog</h1>
        <div id="search-container">
            <input type="text" id="searchInput" placeholder="Search products...">
        </div>
        <div id="product-list" class="product-list"></div>
    </div>
</body>

Давайте добавим некоторые базовые функции JavaScript:

// Product data
const products = [
    { id: 1, name: "Laptop", price: 999.99 },
    { id: 2, name: "Smartphone", price: 699.99 },
    { id: 3, name: "Headphones", price: 199.99 }
];

// Render products
function renderProducts(productsToRender) {
    const productList = document.getElementById('product-list');
    productList.innerHTML = productsToRender.map(product => `
        <div class="product-card">
            <h3>${product.name}</h3>
            <p>$${product.price}</p>
        </div>
    `).join('');
}

// Initial render
renderProducts(products);

Добавление вашего первого React Island

Теперь начинается самое интересное. Давайте узнаем, как обновить наши функции поиска, чтобы использовать React.

  1. First, add React to your page: <script src="https://unpkg.com/react@18/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  2. Создайте свой первый компонент React: функция SearchIsland({ onSearch }) _BOS_ const [searchTerm, setSearchTerm] = React.useState("); const handleSearch = (событие) => { значение константы = event.target.value; setSearchTerm(значение); onSearch(значение); }; return ( <имя класса div="поисковый остров"> <входные данные тип="текст" значение={поисковый термин} onChange={Обработчик поиска} заполнитель="Поиск товаров..." /> <small> Поиск на основе React</small> деленья ); } }
  3. Установите компонент и обеспечьте связь: :функция mountSearchIsland() { const SearchContainer = document.getElementById('поисковый контейнер'); const handleSearch = (поисковый термин) => { константа отфильтрована = продукты.фильтровать(product => product.name.toLowerCase().includes(searchTerm.toLowerCase()) ); Продукты для рендеринга(отфильтрованы); }; ReactDOM.render( <SearchIsland onSearch={handleSearch} />, SearchContainer ); } // Инициализировать mountSearchIsland();

Построение двунаправленной коммуникации

Давайте сделаем все еще интереснее, добавив подборку продуктов, которая объединяет обе стороны:

function ProductIsland({ product, onSelect }) {
    const [isSelected, setIsSelected] = React.useState(false);

    const handleClick = () => {
        setIsSelected(!isSelected);
        onSelect(product, !isSelected);
    };

    return (
        <div 
            className={`product-card ${isSelected ? 'selected' : ''}`}
            onClick={handleClick}
        >
            <h3>{product.name}</h3>
            <p>${product.price}</p>
            {isSelected && <span>✓</span>}
        </div>
    );
}

Обновите свою логику рендеринга:

function renderProducts(productsToRender) {
    const productList = document.getElementById('product-list');
    productList.innerHTML = '';

    productsToRender.forEach(product => {
        const productContainer = document.createElement('div');
        ReactDOM.render(
            <ProductIsland 
                product={product}
                onSelect={(product, isSelected) => {
                    updateCart(product, isSelected);
                }}
            />,
            productContainer
        );
        productList.appendChild(productContainer);
    });
}

Вывод

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

Является ли React Islands будущим веб-разработки? Возможно, не само по себе. Но это часть общей картины того, как мы думаем о создании эффективных веб-приложений. Это дает нам еще один мощный инструмент в нашем арсенале. Главное - понять, когда его следует использовать и, что не менее важно, когда этого не делать.

Дальнейшее чтение

  • Реагируют острова на theguardian.com
  • Острова, серверные компоненты и возможность возобновления работы, о Боже!

Спасибо за чтение и удачного написания кода!