I'm currently working on a next.js project (version 11.1.2) and my goal is to improve the page speed performance. To track this, I am using Google PageSpeed Insight for evaluation. Presently, the scores stand at:
- 40-50 for mobile (!!)
- 80-90 for desktop.
A brief overview:
To enhance specific pages, I have implemented static site generation with incremental static generation. The crucial pages are built during the initial build time while the less significant ones are generated as required. These pages rely on data fetched from Postgres hosted on Heroku.
Steps taken so far:
Upon analyzing in Google PageSpeed Insight, it was evident that the LCP (Largest Contentful Paint) metric is considerably slow (around 6-7s). Therefore, I have already carried out the following tasks:
Optimized images by ensuring each page contains only one preloaded PNG image above the fold. I avoided using the native next/image-component due to variations in image sizes. For other images, I utilized the next/image-component.
In Google PageSpeed Insight, there was a recommendation to "Remove unused JS" present in two next.js files: "/chunks/..." and within the generated page. As a response, I:
- Conducted an analysis using next/bundle-analyzer which pinpointed a heavy library on the client-side. Subsequently, I switched to a lighter alternative but unfortunately did not see any notable improvements in speed.
- Concerning next/dynamic-imports, considering the usage of static site generation, I ponder if additional requests might contribute to a slowdown in performance.
As of now, I am uncertain if my approach is entirely correct. Are there any further optimizations I could implement? Any suggestions or guidance would be greatly appreciated! Thank you!
EDIT Below is the code snippet pertaining to the preloading of the image situated above the fold:
export function SingleItem({ item }){
// some logic
return(
<>
<Head>
<link
rel="preload"
as="image"
href={`/assets/pics/${item.name}.png`} />
</Head>
<div className={styles.image}>
<ItemImage
src={`/assets/pics/${item.name)}.png`}
fallbackSrc="/assets/pic-coming-soon.jpg"
alt="{`${item.name}`}" />
</div>
//more code
</>
)}
The SingleItem-component is utilized in pages/item.js (SSG/ ISG). I am unsure about the feasibility of employing Head-Tags within components.
Furthermore, here is the ItemImage component code:
const ItemImage = (props) => {
const { src, fallbackSrc, ...rest } = props;
const [imgSrc, setImgSrc] = useState(src);
const isSmallScreen = useMediaQuery("(max-width:780px)");
return (
<img
{...rest}
src={imgSrc}
onError={() => {
setImgSrc(fallbackSrc);
}}
className={`${isSmallScreen ? styles.smallImg : styles.bigImg}`}
/>
);
};
//css:
//.bigImg {width: 100%; height: 100%}
//.smallImg {width: 70%; height: 70%}