Skip to content

Next.js Images and Fonts

In modern web development, optimizing images and fonts is crucial for improving website performance and user experience. Next.js provides a series of built-in features that help you easily handle these static assets and achieve automatic optimization.

1. Static File Serving

Next.js serves static files through the public directory, such as images, icons, robots.txt, etc. Any file in the public directory can be accessed through the application's root URL (/).

Example:

  1. Place an image named logo.png in the public directory.
  2. You can reference this image in code via /logo.png.
jsx
function MyLogo() {
  return <img src="/logo.png" alt="My Company Logo" />;
}

Note: Don't use the public directory for compiled assets or dynamically generated files. It should only be used for static assets that don't need build processing.

2. Image Optimization (next/image)

Directly using the HTML <img> tag can lead to performance issues, such as:

  • Loading large images: Even on small screen devices, the original size image is loaded, wasting bandwidth.
  • No lazy loading: Images outside the viewport are loaded immediately, affecting initial page load speed.
  • Layout Shift: Image loading may cause sudden changes in page layout.

To solve these problems, Next.js provides the <Image> component, which is an extension of the <img> tag with automatic image optimization features.

How to Use next/image

  1. Import the component:

    jsx
    import Image from 'next/image';
  2. Use the component:

    jsx
    import profilePic from '../public/me.png'; // Import local image
    
    function MyProfile() {
      return (
        <Image
          src={profilePic} // Can be a statically imported image or a URL string
          alt="Picture of the author"
          width={500} // Must provide dimensions to avoid layout shift
          height={500}
          // placeholder="blur" // Optional: provide blur placeholder
          // blurDataURL="..." // Optional: custom blur placeholder
        />
      );
    }

Core Advantages of next/image

  • Automatic Size Adjustment: Provides correctly sized images based on device screen size.
  • Automatic Lazy Loading: By default, images outside the viewport are lazy loaded.
  • Prevents Layout Shift: By requiring width and height attributes, space is reserved for images to prevent page jumping.
  • Automatic Format Conversion: Can automatically convert images to modern formats (like WebP) to reduce file size.

Remote Images

If you need to load images from external CDNs or other domains, you need to configure allowed domains in the next.config.js file for security.

js
// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        port: '',
        pathname: '/my-bucket/**',
      },
    ],
  },
}

3. Font Optimization (next/font)

Web font loading can also affect performance, potentially causing FOIT (Flash of Invisible Text) or FOUT (Flash of Unstyled Text). Next.js 13 introduced the next/font module for optimizing font loading.

next/font downloads font files at build time and hosts them with other static assets. This means:

  • No External Network Requests: The browser doesn't need to make additional network requests to services like Google Fonts.
  • Privacy Friendly: User information isn't shared with third-party services.
  • Automatic font-display: Automatically sets font-display: optional for optimal performance.

How to Use next/font

Using Google Fonts

  1. Import fonts from next/font/google:

    javascript
    import { Inter, Lusitana } from 'next/font/google';
  2. Load fonts:

    javascript
    const inter = Inter({ subsets: ['latin'] });
    const lusitana = Lusitana({ subsets: ['latin'], weight: ['400', '700'] });
  3. Apply fonts in components:

    You can apply fonts globally or to specific elements.

    Global application (in _app.js):

    jsx
    // pages/_app.js
    import { Inter } from 'next/font/google';
    
    const inter = Inter({ subsets: ['latin'] });
    
    export default function MyApp({ Component, pageProps }) {
      return (
        <main className={inter.className}>
          <Component {...pageProps} />
        </main>
      );
    }

    Local application:

    jsx
    const lusitana = Lusitana({ subsets: ['latin'], weight: ['400', '700'] });
    
    function Heading() {
      return <h1 className={lusitana.className}>My Heading</h1>;
    }

Using Local Fonts

  1. Import from next/font/local:

    javascript
    import localFont from 'next/font/local';
  2. Load local font file:

    javascript
    const myFont = localFont({ src: '../styles/my-font.woff2' });
  3. Apply in components:

    jsx
    function MyComponent() {
      return <p className={myFont.className}>This text uses a local font.</p>;
    }

Summary

Next.js provides powerful built-in optimization features through next/image and next/font that can significantly improve website performance and user experience. By using these tools, you can ensure images and fonts load in the most efficient way while avoiding common performance pitfalls. In the next chapter, we'll explore how to organize and build reusable components and layouts.

Content is for learning and research only.