Comments (14)
Just to give my two cents here - is this really something to implement ourselves? I've been using https://unhead.unjs.io for some time now and really like it, so I wouldn't like to ditch that for vike's implementation. So we should definitely keep it open for users to use their own library / implementation here. On top of that - how would you generally see incorporating that library and focus only on making it work smoothly together?
from vike-vue.
Hi @TimJohns I agree with everything you wrote. I think we removed description
too quickly as we wanted to refactor/simplify things and we underestimated the need for setting a page-specific description that would be updated on client-side navigation.
So yes, please feel free to create one or several PRs (re-)introducting the following settings:
description
canonicalUrl
Looking forward to it 🙏
@brillout FYI feel free to push back as it would be nice to align vike-react
afterwards
from vike-vue.
Actually let me back-pedal a bit. So the reason why we removed description
is because:
- You can now do it through
Head
as you know - There is no need to update the
description
on client-side navigation as a human user wouldn't really care about that description, which is more designed for robots, which are not using client-side navigation.
Argument 2. holds as well for canonicalUrl
. It doesn't hold though for the favicon and the title of the page, which a human user expects to be updated on client-side navigation. That's why we kept these two settings, and only these two.
So I'm changing my mind here: we'd rather not (re-)introduce the description
and canonicalUrl
settings. I apologize if you started working on it.
However, I'd love to see the basic
example extended with canonical URLs, similarly to your snippets. Would you be up for creating a PR for the examples? Thanks a lot 🙏
from vike-vue.
Thanks for the conversation @TimJohns @AurelienLourot.
Yes, that's the reason I only kept title
, favicon
, and lang
: these are the only three <head>
tags I'm aware of that need to be updated upon client-side navigation.
Although I'm realizing that setting a global default description that is being overriden by only some pages is a use case that currently doesn't have a good DX. The issue is that Head
is all-or-nothing: there is no way to tell "only override the description while keeping all other <head>
tags". I'm not sure what we can/should do about this 🤔
@4350pChris WDYT? 👀
from vike-vue.
I would argue that some crawlers are using client-side navigation, like @crawlee/puppeteer.
Even Google has a Javascript SEO thingy.
I'm confident in saying that most crawlers are just plain HTML parsers, but I can see a path where it could negatively impact SEO in some way too.
from vike-vue.
Not to complicate the matter, but one additional consideration worth noting is that while description
(and title
) is typically human-defined by the developer, a reasonable default canonicalUrl
could probably be determined at build time, and may be more appropriately provided programmatically, perhaps in coordination with a plugin that also generates a corresponding sitemap.xml
.
In my case, I provided explicit canonicalUrl
values in the various pages' +config.h.ts
files, but only because my site is small and it seemed easy to do so, and it matched the patterns I saw for the other Head values - there may be a more appropriate mechanism.
In any case, I will see if I can create an example as a basis for reasoning about it, and go from there, and we certainly have my specific actual use case to inform some discussion as well.
Also, thanks for the work on Vike and vike-vue; I am finding it quite useful and I appreciate it.
from vike-vue.
Indeed but I think it is possible already today, inside your implementation of the Head
component, to call usePageContext()
and use the comprehensive information returned to programmatically generate the canonical URL.
from vike-vue.
That (generating canonicalUrl programmatically) seems like it would make a particularly relevant example; I will see what I can come up with there.
from vike-vue.
Keeping this issue open as @brillout and I had a talk earlier today. We're thinking of (re-)introducing more settings like description
for a reason other than crawlers using client-side navigation. Right now the DX is quite convoluted if a user wants to:
- define a
Head
component at the root of their project, and - override only parts of that component for certain pages.
Having more fine-grained settings would alleviate that. On top of that, we'd like some settings to be more "semantic", e.g.:
title
would not only set<title>
but alsoog:title
description
would not only set<meta name="description"
but alsoog:descrption
from vike-vue.
I'll put it here because it is related, even if it is a new feature:
One other attribute related to lang
that should have the same treatment is dir
- for documents in specific languages the direction should be set for the whole document.
from vike-vue.
@pdanpdan 👍 Makes sense and it's on the radar as well.
from vike-vue.
Another possible use case - I'm currently using <teleport>
to add image metadata structured data to <head>
, at run-time on the client, using the approach described in the accepted answer to this stack overflow article. That approach is itself a workaround to <script>
tags being disallowed in component templates, and it would separately be preferable to be able to prerender component-specific structured data in <head>
in any case.
I believe either a fine-grained head settings approach similar to useHead
, or alternately, SSR support for teleport to head (similar to that described in #87) would accomplish that. This is absolutely not a blocker for me - I am including it here and cross-posting in #87 as an example real-world use case for either or both of these features.
If there isn't already a better approach, I am happy to contribute an example that shows the current workaround I'm using, as well as update it with either support for this feature or the one described in #87, as appropriate.
from vike-vue.
I'm actually working on this for vike-react
as we speak.
This is how your use case can be implemented with the upcoming vike-react
release:
import { Head } from 'vike-react/Head'
function Image({ src, author }: { src: string; author: string }) {
return (
<>
<img src={src} />
<Head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org/',
contentUrl: { src },
creator: {
'@type': 'Person',
name: author
}
})
}}
></script>
</Head>
</>
)
}
I guess we can do the same for vike-vue
? Does Vue has something like React's dangerouslySetInnerHTML
?
I am happy to contribute
Yes, contribution welcome! If you're up for it, you could contribute replicating the vike-react/Head
component for vike-vue
. Although note that, while it's all-in-all fairly straighforward (also because I think I've paved a fairly clear path), it isn't completely trivial to implement.
from vike-vue.
Vue has the v-html directive and Render Functions that have the capability of injecting html.
Here's what I am currently doing (directly within +Head.vue for a subset of pages, without the teleport
I mentioned earlier - I keep changing my mind on which approach is cleaner...).
Security Note: I have not thoroughly analyzed this code for the possibility of injection attacks using carefully crafted imgSrc
and copyrightNotice
values, but neither imgSrc
nor copyrightNotice
are user-provided in our use case (and they have been validated and sanitized server-side).
<template class="h-100">
<link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
<title>{{title}}</title>
<meta v-if="description" name="description" :content="description">
<link v-if="canonicalUrl" rel="canonical" :href="canonicalUrl">
<link rel="manifest" href="/favicons/site.webmanifest">
<link rel="shortcut icon" type="image/x-icon" href="/favicons/favicon.ico">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="/favicons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<template v-for="photo in photos">
<ImageObjectJSONLD :contentUrl="photo.imgSrc" :copyrightNotice="photo.copyrightNotice"/>
</template>
<link rel="preconnect" href="https://identitytoolkit.googleapis.com">
<link rel="preconnect" href="https://maps.gstatic.com">
<link rel="preconnect" href="https://accounts.google.com">
<link rel="preconnect" href="https://maps.googleapis.com">
<link rel="preconnect" href="https://lh3.googleusercontent.com">
<link rel="preconnect" href="https://api.epicroadtripplanner.com">
</template>
<script lang="ts" setup>
import { computed, h } from "vue";
import { useData } from 'vike-vue/useData';
import { Data } from './helpers';
const { title, description, canonicalUrl, stopTemplate } = useData<Data>();
const photos = computed(() => (stopTemplate?.photos || []))
type ImageObject = {
'@context': 'https://schema.org/',
'@type': 'ImageObject',
contentUrl: string,
copyrightNotice?: string
}
const ImageObjectJSONLD = (props: {contentUrl: string, copyrightNotice?: string}) => {
const imageObject: ImageObject =
{
'@context': 'https://schema.org/',
'@type': 'ImageObject',
contentUrl: props.contentUrl
};
if (props.copyrightNotice) imageObject.copyrightNotice = props.copyrightNotice;
return h('script', { type: 'application/ld+json', innerHTML: JSON.stringify(imageObject, null, 2)});
}
</script>
from vike-vue.
Related Issues (20)
- Wrong data in `useData` after client side navigation HOT 15
- Possible leftover properties in `pageContextReactive` after `pageChange` HOT 11
- Write docs for `vike-vue-pinia` and `vike-vue-query` HOT 1
- Sell vike-vue + JSX? HOT 1
- vikeVuePinia causes error HOT 4
- using pinia-plugin-persistedstate with js cookie HOT 2
- CSS-in-JS with SSR HOT 33
- How to add some className to body? HOT 9
- How to deploy to IIS server? HOT 1
- Setting the bodyHtmlBegin property breaks the page functionality HOT 16
- Vue Devtools-Next errors when trying to evaluate pageContext HOT 12
- Bug: pageContext.queryClient isn't defined on the client-side HOT 7
- Client side routing with catch all page throwing error HOT 4
- `clientOnly()` function instead of `<ClientOnly>` wrapper component HOT 29
- Progressive Rendering HOT 11
- Nuxt Comparison HOT 4
- Support for `teleports` with Vue SSR HOT 29
- Improve hooks? HOT 20
- Export Vike configuration at `/config`
- Release `vike-vue-{pinia,query}@0.1.0`? HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vike-vue.