Skip to content

fix: improve WebP prioritization and fix image load fallback handling#294

Merged
fzoonoise merged 3 commits intoreadr-media:mainfrom
fzoonoise:feat/2026-01-07_remove-main-image-lazyload
Jan 14, 2026
Merged

fix: improve WebP prioritization and fix image load fallback handling#294
fzoonoise merged 3 commits intoreadr-media:mainfrom
fzoonoise:feat/2026-01-07_remove-main-image-lazyload

Conversation

@fzoonoise
Copy link
Copy Markdown
Contributor

This PR addresses image rendering stability and performance issues by enforcing WebP priority, improving error fallback handling, and renaming a prop to comply with React DOM validation.

Additions

  • Prioritize WebP format in transformImagesSrcSet regardless of existing image preference logic.
  • Add fallback logic to force src usage if srcset fails (prevents dead images).
  • Add debug logs for failed image loads.
  • Add safeguard for empty image lists in loadImageProgress.

Removals

  • N/A

Changes

  • Renamed fetchPriority prop to lowercase fetchpriority to comply with DOM property conventions.
  • Updated getResolution to avoid resolving next image on 'error'; now handled in loadImages.
  • Modified imageSrcSet and imageSizes to be undefined on load/error to trigger fallback behavior.
  • Enhanced loadImageProgress error flow to detect image load failures early.
  • Bump package version from 2.2.6 to 2.2.7.

Testing

  • Verified image rendering with both valid and intentionally broken srcset entries.
  • Confirmed WebP loads when available and fallbacks to src when broken.
  • Manually tested fallback logic with default image on error.

Screenshots

  • N/A

Todos

  • N/A

Task Links

  • N/A

jyunhsin added 3 commits January 14, 2026 19:19
- Update `transformImagesSrcSet` to always prioritize WebP over JPG/PNG for better performance (LCP), regardless of priority settings.
- Remove `srcset` attribute (set to undefined) after image load or on error to force the browser to use the verified `src` URL.
- This prevents dead images when `srcset` contains broken URLs (e.g., missing resized versions) but the fallback `src` is valid.
- Enhance error handling and debug logging in `loadImageProgress`.
@fzoonoise fzoonoise merged commit 696c297 into readr-media:main Jan 14, 2026
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @fzoonoise, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the image rendering component by prioritizing WebP for better performance and implementing comprehensive error handling. It ensures image stability by providing fallbacks when srcset fails and includes safeguards for various loading scenarios, ultimately leading to a more resilient and efficient image display. Additionally, a prop name was adjusted for DOM compliance.

Highlights

  • WebP Prioritization: The image transformation logic now explicitly prioritizes WebP format for improved performance and smaller file sizes, regardless of previous preference logic.
  • Robust Fallback Handling: Implemented a comprehensive fallback mechanism where srcset and sizes are set to undefined on load or error, forcing the browser to use the src attribute to prevent broken images.
  • Error State Management: Introduced an isError state to accurately track image loading failures and trigger appropriate fallback behaviors, including displaying a default image.
  • Debug Logging for Failures: Added debug logs that print messages in development mode when an image fails to load, aiding in troubleshooting.
  • Empty Image List Safeguard: A safeguard has been added to loadImageProgress to throw an error if the provided image list is empty, preventing unexpected behavior.
  • DOM Property Compliance: The fetchPriority prop has been renamed to fetchpriority to comply with standard HTML DOM property conventions.
  • Package Version Bump: The package version has been updated from 2.2.6 to 2.2.7.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves the image component by prioritizing WebP images for better performance and enhancing the fallback logic for greater stability. The changes are logical and well-aligned with the stated goals. I've identified a few areas for improvement: a redundant function call, a potential memory leak with an event listener, and a significant issue with the useEffect dependency array that could lead to bugs when component props change. Addressing these will further improve the component's robustness and maintainability.

@@ -412,6 +421,9 @@ export default function CustomImage({
const loadImageProgress = async () => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The useEffect hook at line 473 calls loadImageProgress, but loadImageProgress is not included in its dependency array. Furthermore, loadImageProgress is redefined on every render and depends on props like images and imagesWebP which are also missing from the useEffect dependency array. This can lead to stale closures and bugs where the component does not react to prop changes.

To fix this, you should wrap loadImageProgress and other functions defined inside the component in useCallback and add them to the useEffect dependency array where appropriate. For example:

const loadImageProgress = useCallback(async () => {
  // ... function body
}, [images, imagesWebP, /* other dependencies */]);

useEffect(() => {
  // ...
  if (!isImageLoaded) {
    // ...
    loadImageProgress();
  }
  // ...
}, [isImageLoaded, loadImageProgress, /* ... */]);

This will ensure that the effect is re-run correctly when its dependencies change, preventing bugs related to stale props.

Comment on lines 423 to 429
const imagesList = getImagesList(images, imagesWebP)
if (imagesList.length === 0) {
throw new Error(errorMessage.noImageProvided)
}
const resolution = await getResolution(imagesList)
const url = await loadImages(resolution, imagesList)
handleImageOnLoaded(url)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The getImagesList function is called here again, but imagesList is already computed in the component's outer scope (line 180). This creates a shadowed variable and is redundant. You can remove the local declaration and use the imagesList constant from the parent scope.

Suggested change
const imagesList = getImagesList(images, imagesWebP)
if (imagesList.length === 0) {
throw new Error(errorMessage.noImageProvided)
}
const resolution = await getResolution(imagesList)
const url = await loadImages(resolution, imagesList)
handleImageOnLoaded(url)
if (imagesList.length === 0) {
throw new Error(errorMessage.noImageProvided)
}
const resolution = await getResolution(imagesList)
const url = await loadImages(resolution, imagesList)
handleImageOnLoaded(url)

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.

1 participant