Skip to content

Conversation

acvigue
Copy link

@acvigue acvigue commented Jul 2, 2024

Closes #1160.

Adds placeholder behavior to NuxtPicture by initially setting the img element's src tag to the placeholder, waiting for the main src to load, and then showing the image.

@acvigue acvigue requested a review from danielroe as a code owner July 2, 2024 23:18
@codecov-commenter
Copy link

codecov-commenter commented Aug 27, 2024

Codecov Report

Attention: Patch coverage is 94.33962% with 3 lines in your changes missing coverage. Please review.

Project coverage is 62.44%. Comparing base (4efdc0b) to head (b0a6bb3).
Report is 307 commits behind head on main.

Files with missing lines Patch % Lines
src/runtime/components/_base.ts 89.28% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1396      +/-   ##
==========================================
+ Coverage   62.20%   62.44%   +0.23%     
==========================================
  Files          79       79              
  Lines        3593     3605      +12     
  Branches      391      401      +10     
==========================================
+ Hits         2235     2251      +16     
+ Misses       1328     1324       -4     
  Partials       30       30              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment on lines +138 to +140
if (mainSrc.value.sizes) img.sizes = mainSrc.value.sizes
if (mainSrc.value.srcset) img.srcset = mainSrc.value.srcset
if (mainSrc.value.src) img.src = mainSrc.value.src
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit worried that we end up loading more images than necessary. So, mainSrc will load, but then if there is another src that better suits browser needs (e.g. avif/webp), this will swap in, and we will have downloaded twice as much image data as we need.

do you have any ideas for resolving that? maybe using a picture element as placeholder instead?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand you here. Do you mean because they use the same picture element, the placeholder will affect the behavior of the <picture> element and make it less efficient? Or that the browser will load the placeholder twice (I don't see how btw)?

Copy link

@prof2k prof2k Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand you now. The browser is forced to download the fallback image source everytime. I think the cleanest solution would be a simple replacement with v-if. Something like this.

<template>
  <!-- Placeholder Image/Picture-->
  <picture v-if="placeholder && !loaded" v-bind="(placeholderClass && placeholder) ? { class: placeholderClass } : {}">
    <source
      v-for="source in placeholderSources.slice(0, -1)"
      :key="source.src"
      :type="source.type"
      :sizes="source.sizes"
      :srcset="source.srcset"
    >
    <img
      ref="imgEl"
      v-bind="{
        ...baseAttrs,
        ...(isServer ? { onerror: 'this.setAttribute(\'data-error\', 1)' } : {}),
        ...imgAttrs,
      }"
      :src="placeholder"
    >
  </picture>
  <!-- Main Image/Picture -->
  <picture v-else>
    <source
      v-for="source in sources.slice(0, -1)"
      :key="source.src"
      :type="source.type"
      :sizes="source.sizes"
      :srcset="source.srcset"
    >
  
    <img
      ref="imgEl"
      v-bind="{
        ...baseAttrs,
        ...(isServer ? { onerror: 'this.setAttribute(\'data-error\', 1)' } : {}),
        ...imgAttrs,
      }"
      :src="sources[lastSourceIndex]?.src"
      :sizes="sources[lastSourceIndex]?.sizes"
      :srcset="sources[lastSourceIndex]?.srcset"
    >
  </picture>
</template>

I wonder if users will want any transition options or it's going to be okay to do an instant swap.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an issue with my code. V-if will not work. But v-show likely will.

@prof2k
Copy link

prof2k commented Jul 10, 2025

Great work guys. Looking forward to this fix. What's the holdup?

@danielroe
Copy link
Member

#1396 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Placeholder for NuxtPicture
5 participants