Up and running with the new Inertia.js Vue 3 adapter
Published on Thursday October 8th, 2020If you're like me and you're into the #goatStack, you might have heard that Inertia.js tagged the first release of their Vue 3 adapater. You can check out the Release notes here.
Now that it's out, you probably want to get in there and give it a try. This post will help you get up and running now, so let's get started.
note for the sake of this post, I will not be focusing on anything outside of getting Inertia JS running.
Getting started
Let's start by getting a brand new Laravel app created
$ laravel new inertia-vue3
The first thing we're going to do is update the package.json file to include the latest version of Laravel Mix, which at the time of writing was 6.0.0-beta.7
. If you check out the project on Github you will see a upgrade.md file on master
branch. This file has a list of changes that have been introduced since V5.
Okay, so your package.json should look like this.
{ "private": true, "scripts": { "dev": "npx mix", "development": "npx mix", "watch": "npx mix watch", "hot": "npx mix watch --hot", "prod": "npx mix --production", "production": "npx mix --production" }, "devDependencies": { "@inertiajs/inertia": "^0.4.0", "@inertiajs/inertia-vue3": "^0.1.0", "@vue/compiler-sfc": "^3.0.0", "axios": "^0.20.0", "laravel-mix": "^6.0.0-beta.7", "postcss": "^8.1.1", "vue": "^3.0.0", "vue-loader": "^16.0.0-beta.8" }}
so let's make some changes. Change your devDependencies
{ "private": true, "scripts": { "dev": "npx mix", "development": "npx mix", "watch": "npx mix watch", "hot": "npx mix hot", "prod": "npx mix --production", "production": "npx mix --production" }, "devDependencies": { "@inertiajs/inertia": "^0.4.0", "@inertiajs/inertia-vue3": "^0.1.0", "axios": "^0.20.0", "laravel-mix": "^6.0.0-beta.5", "vue": "^3.0.0" }}
You can see we changed the "scripts"
object, that's because the new Mix uses npx
commands. Next, let's install our dependencies.
$ npm i // or yarn install
Next, let's jump into our webpack.mix.js
file, by default in Laravel 8 it looks like this.
const mix = require('laravel-mix'); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.js('resources/js/app.js', 'public/js') .postCss('resources/css/app.css', 'public/css', [ // ]);
Now, let's make some changes.
const mix = require("laravel-mix");const path = require("path"); /* |-------------------------------------------------------------------------- | Mix Asset Management |-------------------------------------------------------------------------- | | Mix provides a clean, fluent API for defining some Webpack build steps | for your Laravel applications. By default, we are compiling the CSS | file for the application as well as bundling up all the JS files. | */ mix.postCss("resources/css/app.css", "public/css", [ //]) .js("resources/js/app.js", "public/js") .vue({ version: 3 }); // New Alias pluginmix.alias({ "@": path.resolve("resources/js"),});
Things to note. Mix now has the method .vue()
for, you guessed it compiling vue. You can see we're also passing in an object telling it what version of vue we are working with which is Vue 3.
now if you run npm run dev
you should see this happen.
> npx mix Additional dependencies must be installed. This will only take a moment. Running: npm install @vue/compiler-sfc vue-loader@^16.0.0-beta.8 --save-dev --production=false Okay, done. The following packages have been installed and saved to your package.json dependencies list: - @vue/compiler-sfc - vue-loader@^16.0.0-beta.8 Finished. Please run Mix again.
So let's run npm run dev
again.
you should see this.
Laravel Mix v6 ✔ Compiled Successfully in 1140ms┌───────────────────────────────────┬─────────┐│ File │ Size │├───────────────────────────────────┼─────────┤│ /js/app.js │ 594 KiB │├───────────────────────────────────┼─────────┤│ /css/app.css │ 1 bytes │└───────────────────────────────────┴─────────┘
awesome, now let's configure our app.js to use the new Inertia.
import { createApp, h } from "vue";import { app, plugin } from "@inertiajs/inertia-vue3"; const el = document.getElementById("app"); createApp({ render: () => h(app, { initialPage: JSON.parse(el.dataset.page), resolveComponent: (name) => import(`@/Pages/${name}`).then((module) => module.default), }),}) .use(plugin) .mount(el);
Inertia expects there to be a resources/js/Pages
folder where all your Inertia views will be, so let's create that folder, and add a couple of pages to test it out.
Make 3 pages in resources/js/Pages
. Create a Home.vue
, Blog.vue
and Contact.vue
file.
In Home.vue
add the following.
//Home.vue<template> <h1>Hello from Inertia Vue 3</h1> <inertia-link href="/contact">Contact</inertia-link> <inertia-link href="/blog">Blog</inertia-link></template> <script>export default {};</script>
In Blog.vue
add the following.
//Blog.vue<template> <h1>Hello from Inertia Vue 3</h1> <inertia-link href="/">Home</inertia-link> <inertia-link href="/contact">Contact</inertia-link></template> <script>export default {};</script>
In Home.vue
add the following.
//Contact.vue<template> <h1>Hello from Inertia Vue 3</h1> <inertia-link href="/">Home</inertia-link> <inertia-link href="/blog">Blog</inertia-link></template> <script>export default {};</script>
Once you've done run npm run dev
one more time. If all goes well you should have this output.
Laravel Mix v6 ✔ Compiled Successfully in 1203ms┌───────────────────────────────────┬──────────┐│ File │ Size │├───────────────────────────────────┼──────────┤│ /js/app.js │ 1.13 MiB │├───────────────────────────────────┼──────────┤│ js/resources_js_Pages_Contact_vu… │ 9.7 KiB │├───────────────────────────────────┼──────────┤│ js/resources_js_Pages_Blog_vue.j… │ 9.58 KiB │├───────────────────────────────────┼──────────┤│ js/resources_js_Pages_Home_vue.j… │ 9.57 KiB │├───────────────────────────────────┼──────────┤│ /css/app.css │ 1 bytes │└───────────────────────────────────┴──────────┘
Okay now we have the frontend set up, let's take care of getting the server requirements for Inertia set up. Run the following.
$ composer require inertiajs/inertia-laravel
Next create three controllers.
$ php artisan make:controller HomeController$ php artisan make:controller BlogController$ php artisan make:controller ContactController
Now in our routes/web.php
add this
<?php use App\Http\Controllers\BlogController;use App\Http\Controllers\ContactController;use App\Http\Controllers\HomeController;use Illuminate\Support\Facades\Route; Route::get('/', [HomeController::class, 'index']);Route::get('/blog', [BlogController::class, 'index']);Route::get('/contact', [ContactController::class, 'index']);
In each controller, we're going to have the exact same index
function return an Inertia rendered view.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Inertia\Inertia; class HomeController extends Controller{ public function index() { return Inertia::render('Home'); }}
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Inertia\Inertia; class BlogController extends Controller{ public function index() { return Inertia::render('Blog'); }}
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Inertia\Inertia; class ContactController extends Controller{ public function index() { return Inertia::render('Contact'); }}
Finally, let's make an app.blade.php
in the root of resources/views
. This is what Inertia expects by default.
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel</title> <link rel="stylesheet" href="{{ mix('css/app.css') }}"></head> <body> @inertia <script src="{{ mix('js/app.js') }}"></script></body> </html>
We are simply including our css, js and the @inerta
directive. Once you've done this you should be able to visit your app and see a page like this.
Now you can click around from your home page, to your blog page and contact page.
If you'd like the source code for the project above, you can find it here.
Happy coding!