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)