Upcoming Features in LiveWire 3.0 - Laracon 2023

Wade Zimmerman - Sep 15 '22 - - Dev Community

Today at Laracon, LiveWire announced a major update after nearly 2 years since the last release. The tool was popularized with Laravel 8 in 2020, but faced criticism from many developers. However, after today's news, things are looking up!

Watch


Inspiration/Motivation

Caleb Porzio, the creator of LiveWire and AlphineJS wanted to release a new update because he felt that Alpine and LiveWire were competing with each other too much. He originally envisioned the two libraries working seamlessly, however, many teams view the tools as a tradeoff.

In the upcoming release, devs can build flawless modals, forms, tables, dropdowns, etc. by leveraging both Alpine and LiveWire without increasing technical debt.

To make this possible, Caleb rewrote LiveWire from the ground up so he could rework the underlying plumbing. With a new foundation, LiveWire works like magic and contains more features.


Workflow Updates

When the latest version of LiveWire is released, developers will no longer need to worry about including scripts or even running npm/yarn scripts. Everything will be injected to your app automatically. This includes alpine.

Hot Module Replacement (HMR)

Part of the workflow update and auto injection includes HMR! But wait, unlike popular JS frameworks, you will not need to run any scripts which watch your codebase for changes! Everything just updates on the fly. Unfortunately, Caleb did not disclose how this was possible.


PHP SPA Features

LiveWire now makes it even easier to turn your PHP application into a snappy SPA which was previously only possible when using a JS framework. This is possible through new features such as transitions, client-side routing, and layout persistence.

Transitions

Now you can add some flare to your application when changes are detected. All you have to do is add a wire:transition attribute to a dynamic element.

@foreach ($todos as $todo)
   <li wire:transition>{{ $todo }}</li>
@endforeach

// Or you can do something more unique
@foreach ($todos as $todo)
   <li wire:transition.opacity.duration.2500ms>{{ $todo }}</li>
@endforeach
Enter fullscreen mode Exit fullscreen mode

Client Side Routing & Prefetching

PHP devs are familiar with page navigation. Previously, unless you adopted a framework and migrated a bunch of client side code to JSX, your pages would trigger a full refresh.

Now LiveWire makes it easy to only load the content you need. With the new wire:navigate attribute apps will transition between pages like any other popular SPA.

<nav>
   <a wire:navigate href="/" @active('/')>Todos</a>
   <a wire:navigate.prefetch href="/about" @active('/about')>About</a>
   <a wire:navigate href="/settings" @active('/settings')>Settings</a>
</nav>
Enter fullscreen mode Exit fullscreen mode
Prefetching

Oh, and if you want to prefetch the page when hovering just add the wire:navigate.prefetch attribute.

Layout Persistence

Have you ever used a SPA and wondered how it was possible to navigate between pages while simultaneously persisting state for a specific component like a music player? Well now you don't even have to think about it! Just add a line of code!

This example allows the audio player to keep playing in the background while a user navigates between pages or presses the back button! The key is to use the @persist directive.

<body>
    <x-podcast.header />

    <x-podcast.body>
        {{ slot }}
    </x-podcast.body>

    @persist('player')
        <x-podcast.player />
    @endpersist
</body>
Enter fullscreen mode Exit fullscreen mode

PHP Annotations

LiveWire 3.0 will make heavy use of annotations so devs can quickly change application behavior. Here is a quick overview of what some of the annotations will do.

Annotation Description
@js allows any PHP method to return pure JS. This means you can do not need to write a JS file to control your client-side logic!
@locked make a property immutable. Similar to the final keyword in Java.
@format Quickly format properties which hold a date type.
@prop make a property reactive. For example, if the parent changes the passed in data.
@modelable allow prop to be modeled by parent. When the child value changes notify the parent.

Breaking Changes

There was only one breaking changed announced at Laracon, and that was the behavior for wire:model. In previous version of LiveWire, the modeled data would poll the server frequently, but many developers disliked this framework assumption. In the new version, modeled data is deferred. This means the data change request is sent with the next event such as a button click.

If you need to use the old behavior, then you can easily switch back by using the wire:model.live attribute.


Bundled Requests

Bundle requests ties into the change for wire:model.

Previously, LiveWire would create separate requests for each component and event. This means apps that display multiple components can quickly get bogged down with network requests.

Since Caleb rewrote the underlying plumbing, LiveWire will try to group all updates together to form batch updates. So for example, if you make 3 rapid changes, LiveWire will only send 1 network request containing the 3 changes.


Reactive Props

Unfortunately, it is very difficult to extract LiveWire components into separate files. People that manage to work around this flaw have to create tons of event listeners and hacky JS/PHP to make this work.

Now LiveWire works as expected! You can pass in props like any JS framework, and if the parent mutates the data, the child will reflect the necessary changes.

class TodoCount extends \Livewire\Component
{
    /** @prop */
    public $todos;

    public function render () {
        return <<<'HTML'
             <div>
                 Todos: {{ count($todos) }}
             </div>
        HTML;
    }
}
Enter fullscreen mode Exit fullscreen mode
// elsewhere
<livewire:todo-count :$todos />
Enter fullscreen mode Exit fullscreen mode

Invoke Parent Methods

Likewise, you no longer have to hack together an event system to send data back to the parent. Now you can call parent methods directly by using the $parent syntax.

class TodoInput extends \Livewire\Component
{
    /** @modelable */
    public $value = '';

    public function render () {
        return <<<'HTML'
             <div>
                 <input wire:keydown.enter="$parent.add"
                        wire:model="value" placeholder="Todo" />
             </div>
        HTML;
    }
}
Enter fullscreen mode Exit fullscreen mode

Teleport works in PHP

Teleport is becoming hugely popular in other Frameworks for good reason. Now it is here in LiveWire! If you need to make styling your modal painless, just move it to the body tag! No need to restructure your entire project.

// somewhere in DOM
<div id="footer"></div>

// elsewhere
@teleport('#footer')
  <div>teleport me to footer</div>
@endteleport
Enter fullscreen mode Exit fullscreen mode

Lazy Loading

Finally, it super easy to write components which can be deferred. For example if you need to make an expensive database call, you can show the rest of the page without slowing down your application.

When you use the new lazy attribute, the component will render after it is loaded into the DOM.

To compliment this feature, LiveWire provides a placeholder method which acts as a temporary render method while the component is processing. This is the perfect place to render a spinner component!

class TodoCount extends \Livewire\Component
{
    /** @prop */
    public $todos;

    public function placholder () {
        return <<<'HTML'
             <x-spinner />
        HTML;
    }

    public function render () {

        sleep(2);

        return <<<'HTML'
             <div>
                 Todos: {{ count($todos) }}
             </div>
        HTML;
    }
}
Enter fullscreen mode Exit fullscreen mode
// elsewhere
<livewire:todo-count :$todos lazy />
Enter fullscreen mode Exit fullscreen mode

After Thoughts

I'm still a little skeptical of some of the design choices such as annotations, inline JS, and parent communication.

My main concern is how other developers will adopt these design choices. All of these features have sparked controversy in other languages and frameworks, so I imagine it will not be different for Livewire.

That said, this seems to be a huge improvement from the last version of LiveWire, and I think things are looking up. With these new features, I may consider defaulting to LiveWire for my team's projects.


Conclusion

LiveWire 3.0 looks promising. What do you think?

. . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player