Skip to main content
Back to writing

Livewire 4: single-file components, islands, and the migration tax

Krodox Team July 21st, 2026 Livewire Laravel

Livewire 4 is the biggest change to the library since v3, and unlike Laravel 13 it is not a quiet upgrade. There is genuinely new capability here, and a migration list long enough that it deserves planning.

Components can now be one file

The headline change is component format. Alongside the traditional class-plus-view arrangement, components can be written as single files combining PHP and Blade, or as multi-file components. Slots and automatic attribute forwarding come with it, which makes composition behave much closer to ordinary Blade components.

JavaScript can also live directly in view-based components without wrapping it in @script. Small, but it removes one of the more persistent papercuts of v3.

Islands

Islands let a region of a component update independently of the rest. In v3 a property change re-rendered the whole component and diffed the result; islands narrow that to the region that actually changed.

This matters most on pages where one small piece is busy — a counter, a live status, a polled value — inside a component that is otherwise expensive to render. Previously the fix was to extract a child component largely to protect the parent from re-rendering. Islands address that directly.

Requests stop blocking each other

Several changes point the same direction:

  • Async actions run in parallel rather than queuing behind one another
  • Polling is non-blocking, so a slow poll no longer delays a user interaction
  • Live updates run in parallel

Anyone who has watched a 300ms poll sit in front of a button click will recognise the problem being solved.

New directives

  • wire:sort — drag-and-drop sorting without reaching for a separate library
  • wire:intersect — fires on viewport intersection, with .once, .half and .full modifiers
  • wire:ref — element references without hand-rolled IDs
  • data-loading attributes — loading states become a styling concern rather than a markup one

$errors is now available as a magic property from JavaScript, which closes a gap that previously required passing validation state across the boundary yourself.

The migration list

This is where to spend your planning time.

Routing changed. Route::livewire() is now the required method for full-page components, replacing Route::get(Component::class).

wire:model scope narrowed. It now only listens for events originating on the element itself. If you relied on capturing events from child elements, add .deep to restore that.

Modifier behaviour changed. .blur and .change now control client-side syncing as well. To get v3 behaviour back, prefix with .livewire:model.live.blur.

Endpoint URLs moved. Livewire's endpoints changed from /livewire/ to /livewire-{hash}/, derived from your APP_KEY. Anything with an allowlist, a CDN rule, or a WAF path exception needs updating — this is the change most likely to break in production rather than in development.

Transitions are native now. wire:transition uses the browser's View Transitions API instead of Alpine, and all the custom modifiers (.opacity, .scale, .duration) are gone.

Config keys renamed. layout becomes component_layout and now uses the layouts:: namespace; lazy_placeholder becomes component_placeholder; smart_wire_keys now defaults to true.

JavaScript API changes. $wire.$js() becomes $wire.$js.actionName = () => {}. The commit and request hooks are replaced by interceptMessage() and interceptRequest().

Component tags must be closed. Unclosed tags will not render once slot support is enabled.

Also note stream() changed signature, from stream(to:, content:, replace:) to stream(content:, replace:, el:).

Is it worth it

If you are building interactive interfaces in Livewire, yes — islands and parallel requests address real performance complaints, and single-file components remove a lot of ceremony.

If your Livewire usage is thin, be honest about that before booking the migration. We removed Livewire from this site entirely during a recent rebuild: it was carrying a single dark-mode toggle, with no components of our own, so the dependency cost more than it returned. Alpine covers that ground at a fraction of the weight.

Livewire 4 is a strong release. It is also a real upgrade, and worth the cost only where you are genuinely using what it does.