[2.x] Implement unhead for Vue 3 and its playground #1928
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The current SSR / Head implementation is imho lacking some features and it's a bit cumbersome to configure. I started experimenting with unhead, which is a framework-agnostic implementation and has quite a few nice features.
Using this plugin is still rather similar compared to the current implementation, as the Vue implementation offers a component to be used in templates. Small downside is that there aren't component implementation for React / Svelte, just the composable. Personally I like this approach way more, and seems to be a common approach in React, but I'm not sure about Svelte.
This would however require either user-implementation or providing an Inertia wrapper, since items pushed to the head would need to be disposed when the component unmounts. The
@unhead/vue
package does this, but the bareunhead
package doesn't have this.Note
This PR isn't finished yet, but hopefully provides a good indication of the benefits of using unhead
If there's interest in a full implementation I would love to continue on this
Client implementation / usage
Setup in Vue is rather similar to how you'd set up
unhead
in a regular Vue app;In
ssr.js
this approach is the same. Not the missingtitle
callback, as that's now being dealt with byunhead
. It provides the same functionality as what Inertia provided, along with the ability to use a template.In a page component you'd simply call the
useHead
composable;Server rendering
The server rendering is written in a backwards-compatible way, it will now respond with the following type:
This way the @inertiajs/inertia-laravel implementation can be updated independently. The
head
will now contain head-tags rendered by unhead (skippinghtmlAttrs
andbodyAttrs
).For the backend implementation I'd suggest something like the following, similar to what the unhead docs suggest:
The current implementation in Inertia
The current implementation in Inertia has a few downsides, which I've often ran into
inertia
attribute is added to every tag managed by Inertia. This is a non-standard attribute, lots of checkers complain about this. Not sure if this is allowed in the HTML spec, but also IDEs complain about this. Usingdata-inertia
might be better, but I'd rather see this not being used at all. Unhead does it properly without using an arbitrary attribute.<component is="script">
), with unhead this sort of data is now a lot easierNext steps
React / Svelte
To be able to use this in React / Svelte it would be beneficial to offer unhead through a wrapper. This way Inertia has full control over the lifecycle. The
@unhead/vue
wrapper has some niceties such as supporting refs / computed as input. Harlan Wilton did mention on Discord the plan for v2 of unhead is to support more frameworks. I think Inertia can provide a simple wrapper, and when support for other frameworks land we can just make use of that.Managing the current head
In my current implementation I took a rather simple approach; let the user create a head instance, then during SSR we'd just get that instance through
getActiveHead()
. This might be a bit of a naive approach, it might be better to let Inertia provide this, then users would just consume from it. I think that would also be pretty much solved if we'd provide a wrapper/composable that people can use