Improving Image Loading Efficiency in Next.js - Enhancing Performance by Preloading Images

Currently, I am working on a project in Next.js that involves a scroll-based image loading component. The method I am using to fetch and load images dynamically based on the scroll position is causing performance problems and leading to a less than ideal user experience. To address this issue, I am looking to preload all the images in advance to enhance the speed of the website.

code:

typescript


'use client'

import Image  from 'next/image';
import Link from 'next/link';
import { useEffect, useState } from 'react';

export default function Home() {
  const [headphones, setHeadphones] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      const scrollPercentage = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 180;
      setHeadphones(scrollPercentage);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  
  const imageLoader = () => {
    return `/headphone/${Math.round(headphones)}.png`
  }

  console.log(`/headphone/${Math.round(headphones)}.png`);

  
  // Use dynamic import for the image path
  const imagePath = `/headphone/${Math.round(headphones)}.png`;

  return (
    <main className='h-[100vh] w-[100vw] sticky top-0 flex flex-col justify-center items-center'>  
            {/* Use the next/image component for optimized image loading */}
      <Image
      src={imagePath}
      alt={`Headphone image ${Math.round(headphones)}`}
      width={1920} // specify the actual width of your image
      height={1080} // specify the actual height of your image
      className='w-[calc(100vw-7px)] absolute z-10'
      loader={imageLoader}
      priority
      />
      <div className='w-[100vw] flex flex-col items-end'>
        <div className='flex flex-col items-center'>
          <h1 className={`title text-center w-[7ch] m-[5rem] transition-fade-in ${headphones >= 19 ? 'hidden' : ''}`}>IMMERSE IT IN</h1>
          <p className={`buy transition-fade-in bg-[red] w-[15rem] rounded-full  ${headphones >= 19 ? 'hidden' : ''}`}>BUY</p>
        </div>
      </div>
      <p className={`w-[15ch] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 25 && headphones <= 40 ? 'absolute right-0 bottom-[10%] m-24' : 'hidden'}`}><b className='font-300'>Noise reduction technology</b> for the Best immersion.</p>
      <p className={`w-[18ch] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 25 && headphones <= 40 ? 'absolute left-0 w-[22ch] text-left m-24' : 'hidden'}`}><b  className='font-300'>Talk</b> instead of typing with our <b  className='font-300'>IA powered</b> assistent. <b  className='font-300'>Just ask.</b></p>
      
      <p className={`w-[21ch] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 50 && headphones <= 70 ? 'absolute right-0 bottom-[10%] m-24' : 'hidden'}`}>Revolutionary <b className='font-300'>charging technology</b>. Stay <b className='font-300'>connected</b>.</p>
      <p className={` transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 50 && headphones <= 70 ? 'absolute left-0 top-0 w-[20ch] text-left m-24' : 'hidden'}`}><b className='font-300'>Charge in minutes</b> and <b className='font-300'>use for days.</b></p>
      <p className={` transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 50 && headphones <= 70 ? 'absolute left-0 top-0 w-[20ch] text-left m-24' : 'hidden'}`}><b className='font-300'>Charge in minutes</b> and <b className='font-300'>use for days.</b></p>

      <div className='w-[100vw] flex flex-col items-center'>
        <p className={`text-center w-[100vw] text-[200px] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 70 && headphones <= 100 ? '' : 'hidden'}`}>Connect <b  className='font-300'>Anywhere</b> on <b  className='font-300'>anything</b>.</p>
        <p className={`text-center w-[100vw] text-[50px] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 70 && headphones <= 100 ? '' : 'hidden'}`}>Integrated Adapters for all your devices.</p>
      </div>      
      <p className={` transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 100 && headphones <= 160 ? 'absolute right-0 bottom-0 w-[15ch] text-[150px] text-right m-24' : 'hidden'}`}><b  className='font-300'>2 GB</b> of <b  className='font-300'>memory. Never stop vibing.</b>
      </p>
      <div className='w-[100vw] flex flex-col items-center'>
        <p className={`absolute text-center w-[100vw] text-[150px] tstroke transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 160 ? 'transition-fade-out' : 'hidden'}`}><b className='font-300'>Bluethoth Integrated.</b></p>
        <p className={`text-center w-[100vw] text-[150px] transition-fade-in ${headphones <= 16 ? 'hidden' : headphones >= 160 ? '' : 'hidden'}`}><b className='font-300'>Bluethoth Integrated.</b></p>
      </div>  


    </main>
  )
}

If you'd like to see how my website appears, check it out here: [https://headphone-website-euqrksdu8-au0758s-projects.vercel.app]

Answer №1

Give this performance test a try with Picture imported.

'use client'

import Image from 'next/image';
import { useEffect, useState } from 'react';

const Picture = () => {
  const [earphones, setEarphones] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      const scrollPercentage = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 180;
      setEarphones(scrollPercentage);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  const imageLoader = () => `/earphone/${Math.round(earphones)}.png`;

  const imagePath = `/earphone/${Math.round(earphones)}.png`;

  return (
    <main className='h-[100vh] w-[100vw] sticky top-0 flex flex-col justify-center items-center'>
      <Image
        src={imagePath}
        alt={`Earphone image ${Math.round(earphones)}`}
        width={1920}
        height={1080}
        className='w-[calc(100vw-7px)] absolute z-10'
        loader={imageLoader}
        priority
      />

    </main>
  );
};

export default Picture;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error encountered in React when using Axios to send a POST request: Status code 400 received, indicating request failure

I'm currently working on a React project and facing an issue while trying to make a POST request to my Strapi backend API using Axios. The error message I am encountering is: { "message": "Request failed with status code 400", "name": "AxiosError" ...

Having trouble retrieving the id of the clicked component in dynamic routing with Next.js

Dealing with dynamic routing has been a challenge in my current project. Within the Home component (the main page), I have successfully fetched data from an external API and used map to display it. The goal is for users to click on a product item and get r ...

Module not found

Hey everyone, I recently updated my project to node version v14.18.0, but now I'm encountering a "module not found" issue (see screenshot below). Any suggestions on how to resolve this? https://i.stack.imgur.com/k0u82.png ...

How to resolve the "document is not defined" error in Next.JS when using an external library component?

Currently, I am facing challenges when trying to integrate a component from an external library called 'react-calendly', specifically the PopUpButton widget. This widget needs the parent DOM node to be inserted into. My understanding is that the ...

Getting js.map Files to Function Properly with UMD Modules

I am experiencing an issue with debugging TypeScript files in Chrome and Firefox. Specifically, when trying to debug the MapModuleTest.ts file, the debugger seems to be out of sync with the actual JavaScript code by two lines. This discrepancy makes settin ...

Passing a type as an argument in Typescript

How can I pass a type as a parameter in Typescript? type myType = {} const passingType = (t: Type) => { const x : t = {} } passingType(myType); I keep receiving TypeScript errors. 't' is referencing a value, but it is being used as a t ...

What could be causing the malfunction of my Nextjs Route Interception Modal?

I'm currently exploring a different approach to integrating route interception into my Nextjs test application, loosely following this tutorial. Utilizing the Nextjs app router, I have successfully set up parallel routing and now aiming to incorporate ...

Solving the issue of loading Ember Initializers during the transition to TypeScript

While following the ember quick start tutorial, I attempted to switch from Javascript to Typescript. Converting the .js files to .ts files resulted in an error with the ember-load-initializers import. The application is unable to run until this issue is re ...

I am encountering an issue where the props in NextJS consistently return as undefined

I am currently working on setting up a connection with Contentful. The connection itself seems to be functioning properly and is not the issue, however, when I attempt to transfer the data using props, I keep receiving 'undefined'. I have simpli ...

When a file is modified in Angular, it triggers an error prompting the need to restart the 'npm' service

Whenever I make changes to a file in my Angular application, I encounter the following error: ERROR in ./src/app/@theme/components/auth/index.js Module build failed: Error: ENOENT: no such file or directory, open 'C:\Dev\Ng\ngx-a ...

The link function fails to execute

I have created a custom Directive. The issue I am facing is that the html template is not being rendered. Upon debugging, I noticed that the link function is never called because the instance function is also never called. To troubleshoot, I added "debu ...

Using ngIf for various types of keys within a JavaScript array

concerts: [ { key: "field_concerts_time", lbl: "Date" }, { key: ["field_concert_fromtime", "field_concert_totime"], lbl: "Time", concat: "to" }, { key: "field_concerts_agereq", lbl: "Age R ...

Using Typescript to define property types based on their respective values

Is it possible to set a property type based on the property value? For example, if the command is: If 'set' then the payload must be PayloadSet If 'put' then the payload must be PayloadPut If 'del' then the payload must be ...

What is the best way to retrieve and showcase data in NextJs version 13 and beyond?

Being new to NextJS, my question may seem trivial but I'd appreciate your patience. Essentially, my goal is to fetch data from a database and display it on the page upon the initial render. To achieve this, I am utilizing the useEffect and useState ho ...

Having trouble understanding how to display an HTML file using Next.JS?

Currently, I am working on a project that involves utilizing Next.JS to develop a webpage. The main goal is to display a PDF file on the left side of the screen while integrating Chaindesk on the right side to create a chat bot capable of extracting inform ...

The page is unable to display the data retrieved from the API in Next.js source code

When I fetch data from an API using getServerSideProps with React Query, everything works fine. However, the page source only displays "Loading...", which is not ideal for SEO purposes. Even though I am not utilizing the useEffect Hook, pagination functi ...

Tips for eliminating the undefined/null values from an array nested within another array in Angular

DATA = [{ application: [{ name: 'Room1' },{ name: 'Room2' },{ name: 'Room3' },{ name: 'Room4' },{ name: 'Room5' }], name: 'Batch 1&ap ...

Tips on passing an object as data through Angular router navigation:

I currently have a similar route set up: this.router.navigate(["/menu/extra-hour/extra-hours/observations/", id]) The navigation is working fine, but I would like to pass the entire data object to the screen in order to render it using the route. How can ...

Angular, manipulating components through class references instead of creating or destroying them

I am exploring ways to move an angular component, and I understand that it can be achieved through construction and destruction. For example, you can refer to this link: https://stackblitz.com/edit/angular-t3rxb3?file=src%2Fapp%2Fapp.component.html Howeve ...

How can I verify that the value entered in an input field matches a specific date format such as "MM/dd/YYYY" using Angular?

I need to validate if a given value matches a specific date format such as "MM/dd/YYYY." Typescript file onValChange(event: Date) { const datePipe = new DatePipe('en-US'); const val = datePipe.transform(event, 'MM/dd/yyyy'); ...