Before we delve too deeply into using InertiaJS it’s important to understand the flow that’s happening when a request is made. So, let’s take a moment to understand where AdonisJS ends, where InertiaJS takes over, and what’s passed along to VueJS.
Remember our Vue application is a single-page application (SPA).
The Inertia Render
First let’s tackle the question, “what is inertia.render
doing?” The answer to this question is two-fold depending on whether it’s handling an initial request or subsequent page requests.
The Initial Request
When we make our first page request into our Vue SPA, the inertia.render
call will include our application’s Edge file, which looks like the below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" type="image/png" href="/favicon.ico"> @entryPointStyles('app') @entryPointScripts('app') <title>adonis-inertia-example</title> </head> <body> @inertia() </body> </html>
Copied!
- resources
- views
- app.edge
If you’re familiar with Edge, the only thing unfamiliar with the above should be @inertia()
. In essence, this Edge component is dropping the markup for our Vue application on the page. It doesn’t initialize anything with Vue, it merely drops the div
element that will house our Vue app.
<div id="app" data-page="{ "component": "Home", props: { "testing": "This is a test" }, ... }"></div>
Copied!
The data-page
attribute contains information for the initial state of our Vue app.
Component: The initial page component to display
Props: Data provided to
inertia.render
which will be passed to our page component as props.Url: The current route’s url
Version: The current version for our application, this comes from our manifest file.
So, in essence, for initial requests, inertia.render
will return back the following HTML as it’s response:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" type="image/png" href="/favicon.ico"> <link rel="stylesheet" href="<http://localhost:8080/assets/app.css>"> <script src="<http://localhost:8080/assets/app.js>" defer=""></script> <title>adonis-inertia-example</title> </head> <body> <div id="app" data-page="{ "component": "Home", props: { "testing": "This is a test" }, ... }"></div> </body> </html>
Copied!
In terms of rendering, this is all that’s done on the server-side. Our Vue application isn’t actually instantiated until our app.js
script is loaded in and our createApp
is called.
import '../css/app.css' import { createApp, h } from 'vue' import { createInertiaApp } from '@inertiajs/inertia-vue3' createInertiaApp({ resolve: name => require(`./Pages/${name}`), setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .mount(el) }, })
Copied!
- resources
- js
- app.js
After our Vue application is instantiated everything else, including traveling to other pages is all done on the client-side; apart from grabbing information from Adonis for our routes.
Client-Side Routing
Inertia serves as our client-side router. Similar to Vue Router, Inertia will wrap our application with an inertia
component. This component allows us to easily change pages within our Vue app without needing to re-instantiate our Vue app.
It works in tandem with a special Link
component. In order to traverse from one page to another, we must use this Link
component. Otherwise, the page change will be treated as an initial request and our Vue app will need to be re-instantiated, wasting time and resources for our users.
When we visit another page using this Link
component, the component will kick off a GET request to Adonis for the desired route. This is where we meet inertia.render
once more, this time for a subsequent request. It’ll pick up on this using content negotiation and instead of returning back HTML markup will return back a JSON response containing the same information provided within the data-page
attribute on our initial request.
{ "component":"Home", "version":"e77ee25438e9f73dc55c00b5e3ee4e15", "props": { "testing": "This is a test" }, "url":"/1/dashboard" }
Copied!
The Link Component
Inertia’s Link
component is rather powerful. In this lesson, we’re merely going to take a look at how to use it to get from one page to another. In this section, we’ll be making a login page to serve as our second page.
First, though, let’s learn how to use the Link
component on our home page.
<template> <div> <Link href="/login">Login</Link> <!-- 👈 use it --> <h1>Testing, {{ testing }}</h1> </div> </template> <script> import { Link } from '@inertiajs/inertia-vue3'. // 👈 import it export default { props: { testing: String }, components: { Link // 👈 define it } } </script>
Copied!
First, import it from
@inertiajs/inertia-vue3
.Next, define it as a component, when necessary.
Lastly, use it! Note that
href
is used to specify the path to go to.
Login Page
Next, let’s add our login page so we have an actual page to link to. First, let’s define the route in Adonis.
Route.get('/login', async ({ inertia }) => { return inertia.render('Auth/Login') })
Copied!
- start
- routes.ts
We’ll be putting our authentication-specific pages inside an Auth
folder. So, let’s create our page component at resources/js/Pages/Auth/Login.vue
.
<template> <div> <Link href="/home">Go Home</Link> <h1>Login</h1> </div> </template> <script setup> import { Link } from '@inertiajs/inertia-vue3' </script>
Copied!
Note that since we’re using a setup script here, we don’t need to define the component as we did on our home page.
Testing It Out
With that in place, you should be good to go ahead and test it out! Boot up your server with npm run dev
and click between the home and login pages. You should notice within your developer tool’s inspector that after the initial request, the HTML structure remains the same and only the application’s contents are swapped out.
Additionally, if you inspect the Network tab, you should see a GET request go off every time you swap between pages to capture information for that specific page.
Join The Discussion! (9 Comments)
Please sign in or sign up for free to join in on the dicussion.
Anonymous (EmuSarena790)
Unfortunately I get the following error the moment I introduce the Link component:
VueCompilerError: Invalid end tag.
Please sign in or sign up for free to reply
tomgobich
Sounds like you might have a missing or misspelled end tag, either for the link component or some other element on your page. I'd try double-checking your end tags to ensure one isn't missing or misspelled.
Even if it only happens when you introduce the link component, it could be a missing end tag for an immediate parent or sibling element.
Please sign in or sign up for free to reply
thomaslove
I had the same issue but managed to work it out by cross referencing the docs. Link is capitalised in the import but not in the template. Make sure you're using <Link> and not <link>. The code snippet should read
<Link href="/home">Go Home</Link>
(I realise this a year old, but just in case anyone else runs into the same issue!)
Please sign in or sign up for free to reply
tomgobich
Thank you for the heads-up, I really appreciate it!
I've got the code blocks above updated to use
<Link>
instead of<link>
.Please sign in or sign up for free to reply
pablo
Hi I have followed along but when I attempt to use the Link component I get the following error:
ReferenceError: module is not defined
at ./node_modules/@inertiajs/vue3/dist/index.js
I have used it like so
<script setup lang="ts">
import { Link } from '@inertiajs/vue3'
defineProps({ message: String })
</script>
<template>
<h1> {{ message }} </h1>
<Link href="/test">Test Link</Link>
</template>
Please sign in or sign up for free to reply
pablo
I should add I have installed @inertiajs/vue3 instead of '@inertiajs/inertia-vue3' as the former is the one mentioned in the documentation.
Please sign in or sign up for free to reply
tomgobich
Are you using AdonisJS 5 or AdonisJS 6? Conversely, are you using Inertia 1 or an older Inertia version?
This series was released prior to Inertia 1's release and is meant for AdonisJS 5. The imports used throughout this series will reflect that accordingly.
We're currently in the process of releasing an up-to-date Inertia series, called Building with AdonisJS & Inertia. If you're not working with an older project, I'd recommend following that series instead of this one.
Please sign in or sign up for free to reply
pablo
I am using AdonisJS 5 and using @inertia 0.11.1. I also enabled ts-loader in Webpack Encore as it wouldn't work without it.
I noticed it's crashing when I add the lang="ts" attribute to the script line for example:
// Does not work
<script setup lang="ts">
import { Link } from '@inertiajs/vue3'
</script>
// Works
<script setup>
import { Link } from '@inertiajs/vue3'
</script>
Please sign in or sign up for free to reply
tomgobich
In order to use TypeScript your Inertia code is going to need a separate tsconfig, as the one AdonisJS uses isn't going to be compatible with it.
You may have luck trying to use one similar to the latest Inertia projects, or following an older guide we have on the subject.
I'd personally recommend just getting onto the latest versions though, you're going to have a much easier time.
Please sign in or sign up for free to reply