Building the Modern Monolith: Master Inertia.js with Laravel
Overview of the Inertia Approach
Prerequisites and Tools
To follow this tutorial, you should have a solid grasp of
Key Libraries & Tools
- Laravel: The backend framework handling logic and data.
- Vue 3: The reactive frontend library used for UI components.
- Jetstream: A Laravel starter kit that provides a pre-configured Inertia and Vue environment.
- Vue DevTools: Essential for inspecting page props and state.
- Network Tab: Used to monitor XHR requests and partial data transfers.
The Core Render Flow
In a standard Laravel app, you return view(). In an Inertia app, you return Inertia::render(). This subtle change is where the magic happens. On the initial request, the server sends a full
// In your Laravel Controller
public function index()
{
return Inertia::render('TravelStories/Index', [
'stories' => TravelStory::latest()->get(),
]);
}
On the frontend, the mounted() hook or manage
Navigation and the Link Component
Standard <a> tags cause full page refreshes, wiping out the application state. To achieve a true SPA feel, you must use the <Link> component.
import { Link } from '@inertiajs/vue3';
// Usage in template
<Link href="/statistics" class="btn">View Stats</Link>
When you click this link, Inertia makes an XHR request. The server returns only the data needed for the new page, and Inertia swaps the component out without a browser refresh. This reduces the transfer size from dozens of requests to a single, lean JSON payload.
Optimizing Data with Partial Reloads
Partial reloads allow you to request a subset of data from the server. This is vital for heavy pages where you might only need to update a chart or a list based on a filter. You define these in your controller using closures to ensure they only run when requested.
return Inertia::render('Statistics', [
'chartData' => fn() => $this->getChartData(),
'listData' => Inertia::lazy(fn() => $this->getHeavyData()),
]);
By using Inertia::lazy(), the data is excluded from the initial page load. You can then trigger a load from the frontend using the router.reload method with the only attribute:
router.reload({ only: ['listData'] });
Syntax Notes and Best Practices
Always use
For data required on every page, such as user permissions or global settings, use the HandleInertiaRequests middleware. The share() method merges these global props into every single page response, making them accessible via the usePage() hook without manual controller injection.
Practical Application: Lazy Loading Components
A common real-world use case involves heavy dashboards. You can render the page shell immediately to give the user instant feedback, then use a Vue onMounted hook to trigger a partial reload for the data-intensive parts. This technique provides the fastest possible perceived performance while keeping your backend logic clean and organized.
