
Livewire 4 is the next major version of the popular Laravel full-stack UI framework. It introduces major performance boosts, developer-experience (DX) improvements, and new component conventions — all while aiming to avoid heavy breaking changes.
It’s ideal for Laravel developers who want reactive, dynamic interfaces without switching to a full JS-framework.
Why Should You Upgrade to Livewire 4?
Before we dive into the features, let’s talk about what matters most: performance. Livewire 4 brings massive performance improvements, especially in request handling. Imagine typing in a form with wire:model.live – now all requests run in parallel without blocking each other. What does this mean? More responsive typing, faster results, and a dramatically better user experience.
The same goes for wire:poll. Polling no longer blocks other requests. So if you have a real-time dashboard that needs to update data every few seconds, your app will still feel responsive even with polling running in the background.
Features
Single-File Components: The Simplicity You Need
This is one of the favorite features that will speed up your workflow. Livewire 4 introduces Single-File Components (SFC) that combine PHP and Blade in one file. No more switching back and forth between PHP files and Blade views for simple components.
php artisan make:livewire create-post
With the command above, you’ll get one file containing both logic and template. Simple, clean, and efficient. But don’t worry, if you prefer the traditional structure or need more complex organization, Multi-File Components (MFC) are still available:
php artisan make:livewire create-post --mfc
What’s interesting is that view-based component files now have a ⚡ emoji prefix by default. This makes it easier to distinguish Livewire components from regular Blade files when searching in your editor. If you’re not a fan of emojis, no worries — this can be disabled in the config.
Islands: Maximum Performance Without Complexity
The Islands feature is a game-changer for performance optimization. With Islands, you can create isolated regions within a component that update independently, without creating new child components.
@island(name: 'stats', lazy: true)
<div>{{ $this->expensiveStats }}</div>
@endisland
Imagine you have a dashboard with several widgets. Instead of re-rendering all widgets on every update, with Islands, only the changed widget gets re-rendered. Performance increases dramatically, but code complexity stays minimal.
wire:sort — Drag & Drop Made Easy
Ever felt frustrated implementing drag-and-drop sorting? Not anymore. Livewire 4 brings the wire:sort directive that makes this feature super simple:
<ul wire:sort="updateOrder">
@foreach ($items as $item)
<li wire:sort:item="{{ $item->id }}">
{{ $item->name }}
</li>
@endforeach
</ul>
With just a few lines of code, you have a sortable list with drag-and-drop functionality. No extra libraries needed, no complex JavaScript required.
wire:intersect — Smarter Lazy Loading
The new wire:intersect directive allows you to run actions when elements enter or leave the viewport. It’s perfect for infinite scrolling or lazy loading content:
<div wire:intersect="loadMore">...</div>
You can also add modifiers for more detailed control:
<!-- Load only once -->
<div wire:intersect.once="trackView">...</div>
<!-- Wait until half is visible -->
<div wire:intersect.half="loadMore">...</div>
<!-- Custom threshold -->
<div wire:intersect.threshold.50="trackScroll">...</div>
Async Actions — True Parallel Processing
With the .async modifier, you can run actions in parallel without blocking other requests:
<button wire:click.async="logActivity">Track</button>
Or directly on the method:
#[Async]
public function logActivity() {
// Processing that doesn't need UI updates
}
This is extremely useful for tracking, logging, or background operations that don’t need to wait for UI responses.
More Elegant Loading States
Now every element that triggers a network request automatically gets a data-loading attribute. With Tailwind CSS, styling loading states becomes super easy:
<button wire:click="save"
class="data-[loading]:opacity-50
data-[loading]:pointer-events-none">
Save Changes
</button>
No more separate wire:loading directives for every element. Cleaner and more maintainable.
Deferred Loading — Maximum Page Load Performance
In addition to lazy loading (load when entering viewport), there’s now deferred loading that loads components immediately after the initial page load:
<livewire:revenue defer />
You can also bundle multiple components to load together:
<livewire:revenue lazy lazy:bundle />
<livewire:expenses defer defer:bundle />
More flexible loading strategies make initial page loads faster without sacrificing content.
More Powerful JavaScript Integration
Livewire 4 brings significant improvements to JavaScript integration. View-based components can now include <script> tags directly without the @script wrapper:
<div>
<!-- Component template -->
</div>
<script>
// $wire is automatically bound as 'this'
this.count++
// Or still use $wire
$wire.save()
</script>
These scripts are automatically cached and served as separate files for better performance.
There’s also a new $errors magic property to access the error bag from JavaScript:
<div x-show="$wire.$errors.has('email')">
<span x-text="$wire.$errors.first('email')"></span>
</div>
And $intercept to intercept and modify Livewire requests:
<script>
$wire.$intercept('save', ({ proceed }) => {
if (confirm('Save changes?')) {
proceed()
}
})
</script>
More Consistent Routing
For full-page components, the recommended routing approach now uses Route::livewire():
// Recommended in v4
Route::livewire('/dashboard', Dashboard::class);
// For view-based components
Route::livewire('/dashboard', 'pages::dashboard');
This method is now the standard and required for single-file and multi-file components to work correctly as full-page components.
Upgrading from V3: Not as Hard as You Think
Despite all the new features, the Livewire team has paid close attention to backward compatibility. Most applications can upgrade with minimal changes. The main breaking changes are only in configuration and some method signatures for advanced usage.
Updates You Need to Make
Update composer:
composer require livewire/livewire:^4.0@beta
Clear cache:
php artisan config:clear
php artisan view:clear
Update config file: Some keys in config/livewire.php have changed names or default values. For example:
// Layout configuration
'component_layout' => 'layouts::app', // previously: 'layout'
// Placeholder
'component_placeholder' => 'livewire.placeholder', // previously: 'lazy_placeholder'
// Smart wire:key now defaults to true
'smart_wire_keys' => true,
Features for Advanced Use Cases
Better Interceptor System:
The old commit and request hooks are deprecated, replaced with a more granular interceptor system:
// New interceptor system
Livewire.interceptMessage(({ component, message, onFinish, onSuccess, onError }) => {
onFinish(() => {
// After response received
})
onSuccess(({ payload }) => {
// After successful response
})
onError(() => {
// If there's an error
})
})
This new system differentiates network failures from server errors, supports cancellation, and can be scoped to specific components.
CSP-Safe Mode:
For applications with strict Content Security Policy:
'csp_safe' => true,
This mode uses the Alpine CSP build to avoid unsafe-eval violations. Note that this mode restricts complex JavaScript expressions in directives.
wire:ref — Element References:
Easily reference and interact with elements in your template:
@foreach ($comments as $comment)
<div wire:ref="comment-{{ $comment->id }}">
{{ $comment->body }}
</div>
@endforeach
<button wire:click="$refs['comment-123'].scrollIntoView()">
Scroll to Comment
</button>
Additional Useful Modifiers
- .renderless Modifier: Skip component re-rendering directly from the template:
<button wire:click.renderless="trackClick">Track</button>This is an alternative to the
#[Renderless]attribute for actions that don’t need to update the UI.
- .preserve-scroll Modifier: Preserve scroll position during updates to prevent layout jumps:
<button wire:click.preserve-scroll="loadMore">Load More</button>
Conclusion
This release takes performance, developer experience, and flexibility to an entirely new level. With simplified single-file components, Island architecture for better performance, async actions, and powerful new directives, everything in Livewire 4 is built to make development faster and more enjoyable.
One of the best parts is that you don’t need to overhaul your entire app to benefit. You can adopt the new features gradually — start with what fits your project today, and explore the rest as you go.
If you ever get stuck, the Livewire team has your back. The documentation is detailed, and the community is active and ready to help. Whether you’re upgrading or just experimenting, you’ll find plenty of resources to guide you.
In short, Livewire 4 proves that you don’t need heavy JavaScript frameworks to build modern, dynamic, and high-performing applications. With Laravel and Livewire together, you can deliver a smooth, reactive experience without unnecessary complexity.
And since it’s still in beta, now’s the perfect time to experiment, explore, and share feedback — helping shape the final release into something truly powerful.



