Сравнение Inertia.js и Livewire

inertia vs livewire

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

Inertia.j и Livewire в последнее время находятся в центре внимания. Их часто ставят рядом из-за их одновременных выпусков. Я видел, как многие спрашивают, можно ли их использовать вместе.

Оговорка: я разрабатываю адаптер React для Inertia и использую её ежедневно. Мой опыт с Livewire небольшого масштаба, я просто поиграл с ним, хотя действительно считаю, что хорошо понимаю его общую архитектуру. Тем не менее, это будет объективная статья, я не хочу подталкивать вас в любом направлении, без всяких компромиссов.

Вторая оговорка: обе библиотеки еще молоды, поэтому всё о чём я здесь рассказываю, может быть изменено.

Настройка сцены

Inertia и Livewire родились из-за разочарования в текущем ландшафте JavaScript. Фреймворки, такие как Vue.js или React, позволяют нам создавать невероятные пользовательские интерфейсы, но сложность создания SPA невероятно высока.

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

Livewire — это библиотека Laravel, а Inertia поддерживает адаптеры для разных серверных и клиентских фреймворков. Тем не менее, это сравнение предполагает, что вы хотите использовать Laravel.

Более-менее JavaScript

Давайте начнем с Livewire. На первый взгляд он невидим. Вы создаете свое приложение с Blade, как уже привыкли. Нужно добавить что-нибудь интерактивное? Возьмите немного обычного JavaScript или создайте компонент Livewire.

Компоненты Livewire могут быть встроены в имеющиеся шаблоны:

@livewire('counter')

Простой файла PHP для управления данными и файл Blade для управления шаблоном.

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function render()
    {
        return view('livewire.counter');
    }
}
<div>
  <span>{{ $count }}</span>
</div>

Вы можете привязать данные и события к узлам DOM через wire:, например wire:click. События запускают HTTP-запрос и вызывают связанный с ним метод-обработчик для класса компонента, написанного на PHP.

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function increment()
    {
        $this->count++;
    }

    public function decrement()
    {
        $this->count--;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}
<div>
    <button wire:click="increment">+</button>
    <button wire:click="decrement">-</button>

    <span>{{ $count }}</span>
</div>

Это позволяет создавать интерактивные компоненты без написания JavaScript. Обработка состояний и событий поднимается до класса компонента на сервере.

Inertia — полная противоположность Livewire, когда дело доходит до написания JavaScript. После установки Inertia вы полностью прекращаете писать шаблоны Blade.

В отличие от Livewire, вы возвращаете компоненты из вашего контроллера.

class UsersController
{
    public function index()
    {
        return inertia('Users/Index', [
            'users' => User::all(),
        ]);
    }
}

Inertia отрендерит компонент, написанный на Vue (или выбранном вами фреймворке), в соответствии с указанным вами в ответе путем к компоненту.

<template>
  <table>
    <tbody>
      <tr v-for="user in users" :key="user.id">
        <!-- … -->
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: ['users'],
}
</script>

Вы обрабатываете пользовательские взаимодействия так, как уже привыкли в Vue. Если нужно перейти на новую страницу, используйте компонент InertiaLink. Он запросит JSON через AJAX вместо того, чтобы полностью перезагружать страницу, и ваше приложение приобретет плавность SPA.

<template>
  <table>
    <tbody>
      <tr v-for="user in users" :key="user.id">
        <td>
          <InertiaLink :href="`/users/${user.id}`">
            {{ user.name }}
          </InertiaLink>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: ['users'],
}
</script>

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

<template>
  <div>
    <input type="search" v-model="search">
    <table>
      <tbody>
        <tr v-for="user in users" :key="user.id">
          <td>
            <InertiaLink :href="`/users/${user.id}`">
              {{ user.name }}
            </InertiaLink>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  props: ['users'],

  data() {
    return {
      search: '',
    };
  },

  watch: {
    search(search) {
      Inertia.visit(
        `window.location.href?search=${search}`,
        { preserveState: true }
      );
    }
  }
}
</script>

Опыт разработчика

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

С Inertia вам в значительной степени нужно идти ва-банк (по крайней мере, для каждого раздела приложения). Выборка данных происходит в контроллерах, как вы уже привыкли, но это означает, что вам нужно больше думать о «страницах» и меньше думать о «компонентах» в контексте взаимодействия клиент-сервер.

Оба этих подхода имеют схожий результат: в итоге вы пишете гораздо меньше конечных точек AJAX.

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

С Livewire вы бы написали компонент Livewire таблицы данных, который заботится как о шаблоне, так и о получении данных.

С Inertia вы бы написали одно действие контроллера, которое возвращает шаблон с соответствующими данными. Это работает, потому что каждый последующий запрос уже является запросом AJAX.

Производительность

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

Это обсуждаемый компромисс, когда речь заходит о SPA. В контексте интерактивного веб-приложения дополнительное время загрузки часто стоит тех оптимизаций, которые вы можете выполнить при последующих рендерингах. Обратите внимание, что проигрыш производительности для Inertia намного меньше, чем для SPA. SPA должена сделать дополнительный AJAX запрос на каждой странице для получения данных, в то время как в Inertia, данные немедленно включаются в запрос.

Livewire — совершенно другой зверь. Поскольку он рендерит все на сервере, то проходит очень мало времени до First Meaningful Paint (Первой Интерактивности). После загрузки контента Livewire выполняет свои скрипты и страница станет интерактивной. Предполагая, что вы не загружаете очень много JavaScript, то Time to Interactive (Время, когда пользователь может начать интерактивность) у Inertia и Livewire очень похожи.

Что использовать Inertia или Livewire?

Обычный ответ на все программистские вопросы во вселенной: зависит от.

С точки зрения личных предпочтений

Помимо контекста вашего проекта: если вы предпочитаете работать в Vue, React или другими фронтенд фреймворками, то предпочтете Inertia. Если же любите Blade и хотите меньше писать на JavaScript, то Livewire, вероятно, будет вашим выбором. Однако, это очень субъективно.

С технической точки зрения

Если вы создаете тяжелый рекламный лендинг, блог или что-либо еще с высоким показателем отказов (bounce rate) по своей природе, то более длительное время до Первой Интерактивности может повредить. Livewire подходит для этого лучше. То же самое относится и к страницам, которые должны отображать контент, не полагаясь на JavaScript.

Если вы создаете приложение, это еще более тонкое решение.

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

Inertia ограничивает вас страницами, но позволяет вам добиваться плавного SPA-эффекта во всем приложении.

С точки зрения адаптации

Если вы уже создаете приложения с помощью Laravel и Vue, то Inertia выглядит как шаг вперед по сравнению с монтирования компонентов в шаблоны Blade без кардинальных изменений в структуре приложения. Модель Livewire — большой сдвиг от монолита MVC, который мы привыкли строить.

Заключительные мысли

Имейте в виду, что это очень общий обзор двух библиотек. Они обладают массой мелких функций, которые вызывают радость в повседневной разработке.

У Inertia и Livewire есть одна общая черта: они молодые и очень интересные технологии.

Если вам интересен Livewire, загляните на laravel-livewire.com. Livewire создан и поддерживается Caleb Porzio. Если вы хотите узнать больше о Inertia.js, я настоятельно рекомендую прочитать «Server-side apps with client-side rendering» и «Introducing Inertia.js» от его автора Jonathan Reinink.

Автор: Sebastian De Deyne
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.