2024-08-30
How to Set Up Inertia Components in a Modular Laravel app
I’ve recently been refactoring a big Laravel app into separate modules, following Mateus Guimarães’ excellent Modular Laravel course on Laracasts. One specific topic not covered was how to put front-end components (i.e., from Vue, React, Svelte) inside the module too. This is a quick guide on how I was able to get it to work inside my application.
1. Tell Inertia where to look for front end templates
In my case I’m using a modules
folder, so in app.js/ts
we need to add a line to the array of paths to look for Vue
files:
// ...
createInertiaApp({
resolve: (name) => {
const pages = import.meta.glob([
"./Pages/**/*.vue",
"../../modules/**/*.vue",
]);
for (const path in pages) {
// ...
}
})
2. Put templates in the module
You could set this up in many ways, but I’m choosing a Pages/
directory
directly inside the module. For instance, my CheckIn
module looks like this:
modules/
CheckIn/
...
Pages/
Bear/
Edit.vue
Index.vue
Show.vue
BighornSheep/
And in the CheckInController
, I reference the component like this:
<?php
namespace Modules\CheckIn\Http\Controllers;
use Inertia\Response;
class CheckInController
{
public function index(): Response
{
return inertia('CheckIn/Pages/Index');
}
}
3. Fix component references in tests
If your asserting whether or not a component is rendered in your tests, there’s
one more step you need to take. In config/inertia.php
, add an additional path
to the path_pages
array.
[
// ...
"testing" => [
"ensure_pages_exist" => true,
"page_paths" => [
".../resources/js/Pages",
"modules",
],
// ...
],
]
And finally, in the test:
<?php
test('can access the check-ins page', function () {
$response = $this->get('/check-ins')
->assertInertia(fn (Assert $page) => $page
->component('CheckIn/Pages/Index')
);
$response->assertStatus(200);
});
I like this approach because the component string, e.g.
CheckIn/Pages/Bear/Index
is consistent in the controllers and the tests.