Pre-study
Background
Previously, I tried implementing lazy loading for the <iframe> or updating the URL of the <iframe> (src attribute) on the window load event, as suggested in the posts below. However, when users interact with the <iframe> before all the resources are fully loaded (since the URL is still an empty string), it results in a significant delay while waiting to load the iframe’s resources and perform callback actions.
Optimize Core Web Vitals - FCP and LCP: Lazy-Loading Offscreen <iframe>
Jen C. ・ Mar 18
Optimize Core Web Vitals - FCP and LCP: Lazy-Loading Offscreen <iframe> (2)
Jen C. ・ Apr 17
Solution: Step-by-Step Guide
Use setTimeout to delay URL state update:
When the LazyIframe component mounts, use setTimeout to delay updating the iframe's URL state variable. This ensures the resources load with lower priority but still before the user interacts with the iframe.
Check if iframe URL is already the target URL:
To avoid unnecessary timer creation and state updates, check if the current iframe URL is already equal to the target URL. If they are the same, return early to prevent further action.
Wrap state update with startTransition:
Since the iframe should load with lower priority than user interactions, wrap the state update inside startTransition to ensure that it doesn’t block active user interactions on the page.
Wrap the LazyIframe component with memo:
Use memo to wrap the LazyIframe component. This prevents unnecessary re-renders of the component, improving performance.
Example Implementation of LazyIframe Component
import { useEffect, useState, memo, startTransition } from 'react';
import { MY_AUTH_URL } from '../configs';
const iframeSrc = `${MY_AUTH_URL}/sso/iframePage.xhtml`;
const LazyIframe = memo(function LazyIframe() {
const [src, setSrc] = useState('');
useEffect(() => {
if (src === iframeSrc) {
return;
}
const timer = setTimeout(() => {
startTransition(() => {
setSrc(iframeSrc);
});
}, 100);
return () => clearTimeout(timer);
}, [src]);
return (
<iframe
src={src}
style={{ display: 'none' }}
id='pidiframe'
title='log out iframe'
/>
);
});
Top comments (0)