If 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.
Let's start by getting a brand new Laravel app created
1$ 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.
1{ 2 "private": true, 3 "scripts": { 4 "dev": "npx mix", 5 "development": "npx mix", 6 "watch": "npx mix watch", 7 "hot": "npx mix watch --hot", 8 "prod": "npx mix --production", 9 "production": "npx mix --production"10 },11 "devDependencies": {12 "@inertiajs/inertia": "^0.4.0",13 "@inertiajs/inertia-vue3": "^0.1.0",14 "@vue/compiler-sfc": "^3.0.0",15 "axios": "^0.20.0",16 "laravel-mix": "^6.0.0-beta.7",17 "postcss": "^8.1.1",18 "vue": "^3.0.0",19 "vue-loader": "^16.0.0-beta.8"20 }21}
so let's make some changes. Change your devDependencies
1{ 2 "private": true, 3 "scripts": { 4 "dev": "npx mix", 5 "development": "npx mix", 6 "watch": "npx mix watch", 7 "hot": "npx mix hot", 8 "prod": "npx mix --production", 9 "production": "npx mix --production"10 },11 "devDependencies": {12 "@inertiajs/inertia": "^0.4.0",13 "@inertiajs/inertia-vue3": "^0.1.0",14 "axios": "^0.20.0",15 "laravel-mix": "^6.0.0-beta.5",16 "vue": "^3.0.0"17 }18}
You can see we changed the "scripts"
object, that's because the new Mix uses npx
commands. Next, let's install our dependencies.
1$ npm i // or yarn install
Next, let's jump into our webpack.mix.js
file, by default in Laravel 8 it looks like this.
1const mix = require('laravel-mix'); 2 3/* 4 |-------------------------------------------------------------------------- 5 | Mix Asset Management 6 |-------------------------------------------------------------------------- 7 | 8 | Mix provides a clean, fluent API for defining some Webpack build steps 9 | for your Laravel applications. By default, we are compiling the CSS10 | file for the application as well as bundling up all the JS files.11 |12 */13 14mix.js('resources/js/app.js', 'public/js')15 .postCss('resources/css/app.css', 'public/css', [16 //17 ]);
Now, let's make some changes.
1const mix = require("laravel-mix"); 2const path = require("path"); 3 4/* 5 |-------------------------------------------------------------------------- 6 | Mix Asset Management 7 |-------------------------------------------------------------------------- 8 | 9 | Mix provides a clean, fluent API for defining some Webpack build steps10 | for your Laravel applications. By default, we are compiling the CSS11 | file for the application as well as bundling up all the JS files.12 |13 */14 15mix.postCss("resources/css/app.css", "public/css", [16 //17])18 .js("resources/js/app.js", "public/js")19 .vue({ version: 3 });20 21// New Alias plugin22mix.alias({23 "@": path.resolve("resources/js"),24});
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.
1> npx mix 2 3 Additional dependencies must be installed. This will only take a moment. 4 5 Running: npm install @vue/compiler-sfc vue-loader@^16.0.0-beta.8 --save-dev --production=false 6 7 8 Okay, done. The following packages have been installed and saved to your package.json dependencies list: 9 10 - @vue/compiler-sfc11 12 - vue-loader@^16.0.0-beta.813 14 Finished. Please run Mix again.
So let's run npm run dev
again.
you should see this.
1 2 3 Laravel Mix v6 4 5 6✔ Compiled Successfully in 1140ms 7┌───────────────────────────────────┬─────────┐ 8│ File │ Size │ 9├───────────────────────────────────┼─────────┤10│ /js/app.js │ 594 KiB │11├───────────────────────────────────┼─────────┤12│ /css/app.css │ 1 bytes │13└───────────────────────────────────┴─────────┘
awesome, now let's configure our app.js to use the new Inertia.
1import { createApp, h } from "vue"; 2import { app, plugin } from "@inertiajs/inertia-vue3"; 3 4const el = document.getElementById("app"); 5 6createApp({ 7 render: () => 8 h(app, { 9 initialPage: JSON.parse(el.dataset.page),10 resolveComponent: (name) =>11 import(`@/Pages/${name}`).then((module) => module.default),12 }),13})14 .use(plugin)15 .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.
1//Home.vue 2<template> 3 <h1>Hello from Inertia Vue 3</h1> 4 <inertia-link href="/contact">Contact</inertia-link> 5 <inertia-link href="/blog">Blog</inertia-link> 6</template> 7 8<script> 9export default {};10</script>
In Blog.vue
add the following.
1//Blog.vue 2<template> 3 <h1>Hello from Inertia Vue 3</h1> 4 <inertia-link href="/">Home</inertia-link> 5 <inertia-link href="/contact">Contact</inertia-link> 6</template> 7 8<script> 9export default {};10</script>
In Home.vue
add the following.
1//Contact.vue 2<template> 3 <h1>Hello from Inertia Vue 3</h1> 4 <inertia-link href="/">Home</inertia-link> 5 <inertia-link href="/blog">Blog</inertia-link> 6</template> 7 8<script> 9export default {};10</script>
Once you've done run npm run dev
one more time. If all goes well you should have this output.
1 2 Laravel Mix v6 3 4 5✔ Compiled Successfully in 1203ms 6┌───────────────────────────────────┬──────────┐ 7│ File │ Size │ 8├───────────────────────────────────┼──────────┤ 9│ /js/app.js │ 1.13 MiB │10├───────────────────────────────────┼──────────┤11│ js/resources_js_Pages_Contact_vu… │ 9.7 KiB │12├───────────────────────────────────┼──────────┤13│ js/resources_js_Pages_Blog_vue.j… │ 9.58 KiB │14├───────────────────────────────────┼──────────┤15│ js/resources_js_Pages_Home_vue.j… │ 9.57 KiB │16├───────────────────────────────────┼──────────┤17│ /css/app.css │ 1 bytes │18└───────────────────────────────────┴──────────┘
Okay now we have the frontend set up, let's take care of getting the server requirements for Inertia set up. Run the following.
1$ composer require inertiajs/inertia-laravel
Next create three controllers.
1$ php artisan make:controller HomeController2$ php artisan make:controller BlogController3$ php artisan make:controller ContactController
Now in our routes/web.php
add this
1<?php 2 3 4use App\Http\Controllers\BlogController; 5use App\Http\Controllers\ContactController; 6use App\Http\Controllers\HomeController; 7use Illuminate\Support\Facades\Route; 8 9Route::get('/', [HomeController::class, 'index']);10Route::get('/blog', [BlogController::class, 'index']);11Route::get('/contact', [ContactController::class, 'index']);
In each controller, we're going to have the exact same index
function return an Inertia rendered view.
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use Inertia\Inertia; 7 8class HomeController extends Controller 9{10 public function index()11 {12 return Inertia::render('Home');13 }14}
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use Inertia\Inertia; 7 8class BlogController extends Controller 9{10 public function index()11 {12 return Inertia::render('Blog');13 }14}
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use Inertia\Inertia; 7 8class ContactController extends Controller 9{10 public function index()11 {12 return Inertia::render('Contact');13 }14}
Finally, let's make an app.blade.php
in the root of resources/views
. This is what Inertia expects by default.
1<!DOCTYPE html> 2<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> 3 4<head> 5 <meta charset="utf-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 8 <title>Laravel</title> 9 <link rel="stylesheet" href="{{ mix('css/app.css') }}">10</head>11 12<body>13 @inertia14 <script src="{{ mix('js/app.js') }}"></script>15</body>16 17</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!