Coder Social home page Coder Social logo

Comments (14)

4350pChris avatar 4350pChris commented on September 22, 2024 1

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.

lourot avatar lourot commented on September 22, 2024

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.

lourot avatar lourot commented on September 22, 2024

Actually let me back-pedal a bit. So the reason why we removed description is because:

  1. You can now do it through Head as you know
  2. 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.

brillout avatar brillout commented on September 22, 2024

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.

magne4000 avatar magne4000 commented on September 22, 2024

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.

TimJohns avatar TimJohns commented on September 22, 2024

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.

lourot avatar lourot commented on September 22, 2024

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.

TimJohns avatar TimJohns commented on September 22, 2024

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.

lourot avatar lourot commented on September 22, 2024

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:

  1. define a Head component at the root of their project, and
  2. 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 also og:title
  • description would not only set <meta name="description" but also og:descrption

from vike-vue.

pdanpdan avatar pdanpdan commented on September 22, 2024

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.

brillout avatar brillout commented on September 22, 2024

@pdanpdan 👍 Makes sense and it's on the radar as well.

from vike-vue.

TimJohns avatar TimJohns commented on September 22, 2024

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.

brillout avatar brillout commented on September 22, 2024

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.

TimJohns avatar TimJohns commented on September 22, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.