Lazy Loading in Next.js

Next.js already has built in lazy loading support. Routes are already lazy loaded unlike React Router. Using next/image already automatically does lazy loading.

Let's see how we can lazy load even more parts of our site so that our users get an even faster experience. We will even see how we can lazy load Next.js when things scroll into view

The smaller bundle sizes we send to users when they land on our pages, the faster their browsing experience.

next/dynamic is the built in Next.js package to lazy load components.

jsx
import dynamic from 'next/dynamic'

const Comments = dynamic(() => import('../components/comments'))

Once the component is supposed to be rendered to the page, Next.js will load it. You can see the proof of this in your DevTools Network tab.

Lazy Loading in DevTools Network Tab

It's important to note that a component will be loaded if it is rendered (even if it is not in the viewport).

To dynamically load something, there needs to be a conditional loading. In the example below, we must press a button to show the comments.

jsx
import { useState } from "react";
import dynamic from "next/dynamic";
const Comments = dynamic(() => import("../components/Comments"));

export default function Home() {
  const [showComments, setShowComments] = useState(false);

  return (
    <>
      {/* button to show comments */}
      <button onClick={() => showComments(true)}>Load Comments</button>

      {/* comments only loaded if showComments is true */}
      {showComments && <Comments />}
    </>
  );
}

To lazy load on scroll, we will use a React scrolling package. There are many but we will use react-cool-inview.

jsx
import useInView from "react-cool-inview";
import dynamic from "next/dynamic";
const Comments = dynamic(() => import("../components/Comments"));

export default function Home() {
  const { observe, inView } = useInView({
    onEnter: ({ unobserve }) => unobserve(), // only run once
  });

  return (
    <>
      {/* adding some height so we have to scroll down */}
      <div style={{ minHeight: '1000px' }}>Scroll Down</div>

      {/* bind the observe to this ref so we can watch this element entering/exiting the viewport */}
      {/* when this comes into view, inView will be true */}
      <div ref={observe}>
        {/* comments will load when inView is true */}
        {inView && <Comments />}
      </div>
    </>
  );
}
  • We use observe on the element we want to watch
  • inView will become true when this comes into the viewport
  • Comments will load dynamically when inView is true

We can use this lazy loading in Next.js technique for many things like ads, analytics, comments, or any component that isn't necessary for first page load.

Chris Sev

Chris Sev

Chris Sev is the co-founder of Better Dev. Coding better every day. Previously he created Scotch.io which was acquired.