Developing a Laravel package with Laravel Mix and Inertia.js
You can directly skip to “Installing Laravel Mix and Inertia.js” if you already know how to setup a package or have a package you’re working in.
Scaffolding our project
Let’s get started by scaffolding a project where we develop our package. Spin up your terminal and create a new Laravel project:
cd ~/Sites
laravel new our-awesome-package
cd our-awesome-package
Great, that should’ve taken a few seconds with Composer 2. Now, let’s create a basic setup for our package. For the sake of simplicity (and my personal preference) we’re going to use a template made by Spatie: spatie/package-skeleton-laravel this template takes care of the boring boilerplate stuff.
Also noteworthy: the template comes with a package called
laravel-package-tools
. This makes registering commands, routes and views as simple as chaining a few methods.
Okay, let’s make use of this:
mkdir packages
cd packages
git clone [email protected]:spatie/package-skeleton-laravel.git YOUR_PACKAGE_NAME
cd YOUR_PACKAGE_NAME
We almost have everything in place. Let’s finish this by running bash configure-skeleton.sh this will do the rest for us.
Once you’ve completed these steps you’ll have to include the package in your actual Laravel app. You’ll do this by
- Add it to your composer.json repositories array
- Require the local package
Open your project’s composer.json (not the one inside your package) and add the following:
"repositories": [
{
"type": "path",
"url": "./packages/PACKAGE_DIRECTORY_NAME"
}
],
Now we’re able to require the package by running composer require YOUR_VENDOR_NAME/YOUR_PACKAGE_NAME
. Awesome, let’s proceed to the part what the blog is about.
Installing Laravel Mix and Inertia.js
First, we need to install our packages. Let’s start with that:
npm init -y
npm i -D @inertiajs/inertia @inertiajs/inertia-vue vue laravel-mix
composer require inertiajs/inertia-laravel
Let’s not forget to add our script to the package.json:
"scripts": {
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"production": "mix --production"
}
Right, that wasn’t difficult. We now have Inertia.js, Vue and Inertia for Laravel. I guess you also came this far before consulting this blog post.
Setting up Laravel Mix
Let’s create the webpack.mix.js configuration file which does the magic:
const mix = require('laravel-mix')
mix.setPublicPath('public').copy(
'public',
'../../public/vendor/YOUR_PACKAGE_NAME'
)
mix.js('resources/js/app.js', 'public/js')
.vue({ version: 2 })
.postCss('resources/css/app.css', 'public/css')
if (mix.inProduction()) {
mix.version()
}
Got it? No worries. I’ll explain what’s happening. We’re setting the public path to public and copy over the whole public folder to our app’s public folder under the vendor/YOUR_PACKAGE_NAME name.
So, our app.js will resolve to https://ourapp.com/vendor/YOUR_PACKAGE_NAME/app.js, the same applies to app.css of course. We’re not done yet. Let’s continue with setting up Inertia.
Setting up Inertia
Cool, we can now continue with setting up Inertia. Let’s create an app.js entry inside resources/js/app.js and an empty resources/css/app.css so our Laravel Mix won’t break.
We’ll blindly follow the Inertia docs until we hit our next roadblock:
// resources/js/app.js
import { App, plugin } from '@inertiajs/inertia-vue'
import Vue from 'vue'
Vue.use(plugin)
const el = document.getElementById('app')
new Vue({
render: h =>
h(App, {
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => require(`./Pages/${name}`).default,
},
}),
}).$mount(el)
And our middleware of course. Make sure you set the $rootView correctly:
<?php
// src/Http/Middleware/HandleInertiaRequests.php
namespace YOUR_VENDOR_NAME\YOUR_PACKAGE_NAME\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
/**
* The root template that's loaded on the first page visit.
*
* @see https://inertiajs.com/server-side-setup#root-template
* @var string
*/
protected $rootView = 'PACKAGE_NAME::app';
/**
* Determines the current asset version.
*
* @see https://inertiajs.com/asset-versioning
* @param \Illuminate\Http\Request $request
* @return string|null
*/
public function version(Request $request)
{
return parent::version($request);
}
/**
* Defines the props that are shared by default.
*
* @see https://inertiajs.com/shared-data
* @param \Illuminate\Http\Request $request
* @return array
*/
public function share(Request $request)
{
return array_merge(parent::share($request), [
//
]);
}
}
We’re almost set. All what’s left is creating a route, view and set the middleware. So let’s do that.
First, register a base view for our Inertia app:
<!-- resources/views/app.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Don't forget to use your package name -->
<link rel="stylesheet" href="{{ mix('css/app.css', 'vendor/YOUR_PACKAGE_NAME') }}">
<script src="{{ mix('js/app.js', 'vendor/YOUR_PACKAGE_NAME') }}" defer></script>
</head>
<body>
@inertia
</body>
</html>
Then we’ll create the routes:
<?php
// routes/web.php
Route::middleware(['web', HandleInertiaRequests::class])->get('our-package', function () {
return inertia('Home');
});
And after that we’ll create the Vue component:
<!-- resources/js/Pages/Home.vue -->
<template>
<div>We did it!</div>
</template>
Let’s see if it works by running npm run watch and visiting /our-package. That’s it.
I’d recommend to to check out these links if you want to know more or if it’s still not working:
- Inertia.js documentation
- Laravel package documentation
- Spatie’s Laravel package skeleton
- Spatie’s Laravel package tools
- Laravel package development guide