Say hello to the Inertia Head component

Published on Tuesday June 1st, 2021
Say hello to the Inertia Head component

With the newest release of Inertia.js comes a new component called "Inertia head". This new component allows you to update the <title> and <meta> tags inside the <head> tag of your HTML. Before this component, trying to change the <title> of your page, although not impossible, wasn't very easy. Not only can you do this with ease within your page component, but you can also take advantage of any props passed to your page.

Imagine being able to set your Open Graph tags dynamically or updating the page's title when your user is reading an article, or even changing the favicon; all of this is possible.

To demonstrate this new feature, let's start using my favourite Laravel starter kit Laravel Breeze.

Start by creating a new Laravel app.

laravel new inertia-head-demo

Once this is run, cd into your new project and run

composer require laravel/breeze --dev

followed by

PHP artisan breeze:install vue

Once this has run, you should see your devDependencies of your package.json have been updated and look like this.

"devDependencies": {
"@inertiajs/inertia": "^0.8.4",
"@inertiajs/inertia-vue3": "^0.3.5",
"@inertiajs/progress": "^0.2.4",
"@tailwindcss/forms": "^0.2.1",
"@vue/compiler-sfc": "^3.0.5",
"autoprefixer": "^10.2.4",
"axios": "^0.21",
"laravel-mix": "^6.0.6",
"lodash": "^4.17.19",
"postcss": "^8.2.13",
"postcss-import": "^14.0.1",
"tailwindcss": "^2.1.2",
"vue": "^3.0.5",
"vue-loader": "^16.1.2"
}

To take advantage of this <inertia-head> we need to bump the version of @inertiajs/inertia, @inertiajs/inertia-vue3. While we are at it we can also updated @inertiajs/progress to the latest version, but this isn't required.

"devDependencies": {
"@inertiajs/inertia": "^0.9.1",
"@inertiajs/inertia-vue3": "^0.4.2",
"@inertiajs/progress": "^0.2.5", // optional
...
}

Next, let's install our JavaScript dependencies and build our assets and watch for changes.

npm install && npm run watch

Next, we want to edit our app layouts and add <inertia-head> tags. What we set here will be the "defaults" that we can override at the page level.

In Breeze, there are two layout components, Guest.vue located at resources/js/Layouts/Guest.vue and Authenticated.vue located at resources/js/Layouts/Authenticated. vue The Guest.vue layout gets used by all the auth views, and Authenticated.vue gets used once the user has authenticated and is viewing their dashboard. For this example, we will focus on the auth screens and the Guest.vue layout; add the following to Guest.vue layout anywhere in the <template> tags.

<inertia-head title="Inertia Head Demo" />

I am using Laravel Valet locally, so if I go and visit http://inertia-head-demo.test/login I should expect to see the title for that page to be "Inertia Head Demo", but visiting /login to check, the title will show "Laravel" or whatever your is in your .env setting for APP_NAME. The reason for that is there should only ever be one <title> tag on the page, and if there are more than one, the first one that appears on the page will take priority. If you check the app.blade.php file, you'll see this on line 8

<title>{{ config('app.name', 'Laravel') }}</title>

If you delete the above line and refresh the page, we should see the title we set in our layout.

Good stuff, right? Okay, let's take that next step. Open Login.vue and add a <inertia-head> tag to overwrite the default we set in the Guest.vue

<inertia-head title="Inertia Head Demo - Login" />

Now when you visit /login, you will see Inertia Head Demo - Login in your browser tab as the title.

browser tab screenshot

Open Graph meta tags

Facebook and Twitter both allow you to customize what the preview for a URL looks like. You can read about Facebook's OG tags here and Twitter cards here.

Let's start by updating the default <inertia-head> component we added to Guest.vue add the following.

<inertia-head>
<title>Inertia Head Demo</title>
<meta type="description" content="Inertia Head Demo." />
<meta name="twitter:title" content="Inertia Head Demo" />
<meta name="twitter:site" content="@ninjaparade" />
<meta name="twitter:creator" content="@ninjaparade" />
<meta name="twitter:description" content="Inertia Head Demo." />
<meta name="twitter:card" content="summary_large_image" />
 
<meta property="og:url" content="http://inertia-head-demo.test" />
<meta property="og:title" content="Inertia Head Demo" />
<meta property="og:description" content="Inertia Head Demo" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" />
</inertia-head>

Now visit /login, and you should see this.

<head>
<title inertia="">Inertia Head Demo </title>
<meta type="description" content="Inertia Head Demo." inertia="" />
<meta property="og:url" content="http://inertia-head-demo.test" inertia="" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" />
<meta name="twitter:title" content="Inertia Head Demo." inertia="" />
<meta name="twitter:site" content="@ninjaparade" inertia="" />
<meta name="twitter:creator" content="@ninjaparade" inertia="" />
<meta name="twitter:description" content="Inertia Head Demo." inertia="" />
<meta name="twitter:card" content="summary_large_image" inertia="" />
<meta property="og:title" content="Inertia Head Demo." inertia="" />
<meta property="og:description" content="Inertia Head Demo." inertia="" />
<meta property="og:type" content="website" inertia="" />
</head>

You can see the OG Meta tags, followed by the title. The defaults are used here, and since we set the title in the <inertia-head> on our Login.vue page, we see Inertia removing the default title and using the one from our page component.

Now let's try to set the OG tags in our Login.vue component. I'm going to add this.

<inertia-head>
<title>Inertia Head Demo - Login</title>
<meta type="description" content="Inertia Head Demo - Login page." />
<meta name="twitter:title" content="Inertia Head Demo - Login page." />
<meta name="twitter:site" content="@ninjaparade" />
<meta name="twitter:creator" content="@ninjaparade" />
<meta name="twitter:description" content="Inertia Head Demo - Login page." />
<meta name="twitter:card" content="summary_large_image" />
 
<meta property="og:url" content="http://inertia-head-demo.test/login" />
<meta property="og:title" content="Inertia Head Demo - Login page." />
<meta property="og:description" content="Inertia Head Demo - Login page." />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" />
</inertia-head>

Now refresh and visit /login... WHAT IS HAPPENING!?

<head>
...
<meta type="description" content="Inertia Head Demo." inertia="" />
<meta property="og:url" content="http://inertia-head-demo.test" inertia="" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" />
<meta name="twitter:title" content="Inertia Head Demo." inertia="" />
<meta name="twitter:site" content="@ninjaparade" inertia="" />
<meta name="twitter:creator" content="@ninjaparade" inertia="" />
<meta name="twitter:description" content="Inertia Head Demo." inertia="" />
<meta name="twitter:card" content="summary_large_image" inertia="" />
<meta type="description" content="Inertia Head Demo - Login page." inertia="" />
<meta name="twitter:title" content="Inertia Head Demo - Login page." inertia="" />
<meta name="twitter:site" content="@ninjaparade" inertia="" />
<meta name="twitter:creator" content="@ninjaparade" inertia="" />
<meta name="twitter:description" content="Inertia Head Demo - Login page." inertia="" />
<meta name="twitter:card" content="summary_large_image" inertia="" />
<meta property="og:url" content="http://inertia-head-demo.test" inertia="" />
<meta property="og:title" content="Inertia Head Demo - Login page." inertia="" />
<meta property="og:description" content="Inertia Head Demo - Login page." inertia="" />
<meta property="og:type" content="website" inertia="" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="" />
<title inertia="">Inertia Head Demo - Login</title>
</head>

Our <head> tag now duplicates our meta tags and empty inertia attributes; why is this happening? The <inertia-head> component will always ensure only one <title> tag. When it comes to the <meta> tags <inertia-head> is simply going to take the defaults and the <meta> tags from the Login.vue component and stack them which is why you see them duplicated. Thankfully fixing this is pretty straightforward. We can tell <inertia-head> how to handle duplicates by adding a head-key property. This will make sure the tag is only rendered once.

So change the Guest.vue Inertia head to this.

<inertia-head>
<title>Inertia Head Demo</title>
<meta head-key="description" type="description" content="Inertia Head Demo." />
<meta head-key="twitter:title" name="twitter:title" content="Inertia Head Demo." />
<meta head-key="twitter:site" name="twitter:site" content="@ninjaparade" />
<meta head-key="twitter:creator" name="twitter:creator" content="@ninjaparade" />
<meta head-key="twitter:description" name="twitter:description" content="Inertia Head Demo." />
<meta head-key="twitter:card" name="twitter:card" content="summary_large_image" />
 
<meta head-key="og:url" property="og:url" content="http://inertia-head-demo.test" />
<meta head-key="og:title" property="og:title" content="Inertia Head Demo." />
<meta head-key="og:description" property="og:description" content="Inertia Head Demo." />
<meta head-key="og:type" property="og:type" content="website" />
<meta head-key="og:image" property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" />
</inertia-head>

And change the <inertia-head> component in Login.vue to

<inertia-head>
<title>Inertia Head Demo - Login</title>
<meta head-key="description" type="description" content="Inertia Head Demo - Login page." />
<meta head-key="twitter:title" name="twitter:title" content="Inertia Head Demo - Login page." />
<meta head-key="twitter:site" name="twitter:site" content="@ninjaparade" />
<meta head-key="twitter:creator" name="twitter:creator" content="@ninjaparade" />
<meta head-key="twitter:description" name="twitter:description" content="Inertia Head Demo - Login page." />
<meta head-key="twitter:card" name="twitter:card" content="summary_large_image" />
 
<meta head-key="og:url" property="og:url" content="http://inertia-head-demo.test/login" />
<meta head-key="og:title" property="og:title" content="Inertia Head Demo - Login page." />
<meta head-key="og:description" property="og:description" content="Inertia Head Demo - Login page." />
<meta head-key="og:type" property="og:type" content="website" />
<meta head-key="og:image" property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" />
</inertia-head>

let your assets recompile and refresh and you should see this.

<head>
...
<title inertia="">Inertia Head Demo - Login</title>
<meta type="description" content="Inertia Head Demo - Login page." inertia="description" />
<meta property="og:url" content="http://inertia-head-demo.test" inertia="og:url" />
<meta property="og:image" content="https://www.biography.com/.image/t_share/MTQ3NTI2OTA4NzY5MjE2MTI4/drake_photo_by_prince_williams_wireimage_getty_479503454.jpg" inertia="og:image" />
<meta name="twitter:title" content="Inertia Head Demo - Login page." inertia="twitter:title" />
<meta name="twitter:site" content="@ninjaparade" inertia="twitter:site" />
<meta name="twitter:creator" content="@ninjaparade" inertia="twitter:creator" />
<meta name="twitter:description" content="Inertia Head Demo - Login page." inertia="twitter:description" />
<meta name="twitter:card" content="summary_large_image" inertia="twitter:card" />
<meta property="og:title" content="Inertia Head Demo - Login page." inertia="og:title" />
<meta property="og:description" content="Inertia Head Demo - Login page." inertia="og:description" />
<meta property="og:type" content="website" inertia="og:type" />
</head>

That's it! There is more to discuss about <inertia-head> and where it really shines when paired with an upcoming feature to provide server-side rendering for Inertia. SSR for Inertia is ready to be used and is currently powering the Inertia.js website, but documentation on how to get this working on Laravel Forge and Heroku are currently available to Inerita sponsors.

Thanks for reading and feel free to reach out on Twitter if you got any questions.

© 2024   Ninjaparade Digital Inc.   All Rights Reserved.