vue.jsnuxt.jslazy-loadingserver-side-renderingsrc

How to properly lazy-load images in Nuxt?


Is it possible to use both - ssr and lazy-loading for images on the client side. Here is my situation. My markup is rendered with img[src], in my chrome browser I press ctrl+U and can see all images have an src attribute (seo robots will recognize them and I'm happy), but on the client side I need to have img[data-src] for lazy-loading. If I have a data-src attribute on the server-side, the seo robots won't find any src (pressing ctrl + U will prove it), but all images will be displayed with lazy loading... Should I filter the markup before receiving on the client side (actually I'm sure how to implement it in nuxt). Please suggest any ideas or directions to solve the issue?


Solution

  • Here is how to achieve the following:

    <template>
      <div>
        <pre>all the interesting images: {{ pokemon.sprites.other }}</pre>
        <div class="reference-breakpoint"></div>
    
        <p>Down below are all the remaining images ⬇️</p>
        <img :src="pokemon.sprites.other.dream_world.front_default" />
        <img
          class="hide-when-mobile"
          loading="lazy"
          :src="pokemon.sprites.other.home.front_default"
        />
        <img
          class="hide-when-mobile"
          loading="lazy"
          :src="pokemon.sprites.other.home.front_shiny"
        />
        <img
          class="hide-when-mobile"
          loading="lazy"
          :src="pokemon.sprites.other['official-artwork'].front_default"
        />
      </div>
    </template>
    
    <script>
    export default {
      async asyncData({ $axios }) {
        const pokemon = await $axios.$get(
          'https://pokeapi.co/api/v2/pokemon/charizard'
        )
        return { pokemon }
      },
    }
    </script>
    
    <style scoped>
    img {
      display: block;
      height: 100vh;
      width: auto;
    }
    .reference-breakpoint {
      width: 1000px;
      height: 1rem;
      background-color: red;
    }
    @media (max-width: 1000px) {
      .hide-when-mobile {
        display: none;
      }
    }
    </style>
    

    Not satisfied with this one? Here is an intersectionObserver example, a bit more complex but also more powerful/flexible.