How does Next.js basePath works for images?
Asked Answered
Q

2

7

I'm trying to add a basePath to my next.config.js, it works well for the website content. But all the images are broken.

// next.config.js
module.exports = {
  basePath: '/my-sub-url',
  assetPrefix: '/my-sub-url/'
}

I also tried adding all the image path to something like this:

src="/my-sub-url/image.jpg"

And I also tried created a my-sub-url folder in my public folder, but still no luck.

My codes and images are all in my GitHub private project, and I'm deploying using Vercel.com. Currently I'm in Next.js v10 canary.

Is this because I host my images in GitHub? Or any other settings that I've missed out on? Don't seem to be find anything in Vercel/Next.js docs and other online places.

Quaquaversal answered 28/1, 2021 at 3:49 Comment(2)
Where are the images located within your Next.js app? Are you serving them from the public/ folder?Triecious
@Triecious yup they are all in public/Quaquaversal
S
1

Since the basePath property in next.config.js effectively changes all other links, and if the use case is limited only to images being loaded from the public/ folder or some directory in it. I found some solution which can avoid rewriting all src attributes of Image elements in the project.

// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
    basePath:"/your-base-path",
    images:{
        loader:"custom",
        loaderFile:"/path/to/custom-image-loader.js",
    }
}

module.exports = nextConfig

//custom-image-loader.js

import { basePath } from "../next.config";
import path from "path";


export default function myImageLoader({src,width}) {
  if( basePath && path.isAbsolute(src) ){
    return `${basePath}${src}?width=${width}`;
  }
  return `${src}?width=${width}`;
}

After adding this to your project. Mostly all image src attributes which are not absolute URLs (external links) should be accessible without having to add basePath to each Image component.

Spiel answered 25/3 at 16:55 Comment(0)
L
0

The official Next.js documentation states that basePath is needed to be explicitly coded in the Images[Src] attribute.

So, if you setup your basePath in the next.config.js, like this:

      /** @type {import('next').NextConfig} */
    const nextConfig = {
    basePath: '/absproxy/3000',
    assetPrefix: '/absproxy/3000',
    reactStrictMode: true,
    swcMinify: true,
    trailingSlash: true,
    async rewrites() {
        return [
        {
            source: '/images/:path*',
            destination: '/absproxy/3000/images/:path*', // The :path parameter isn't used here so will be automatically passed in the query
        },
        ]
    },
    images: {
        path: '/absproxy/3000/_next/image',
    },
    }

    module.exports = nextConfig

Then I have my flower.jpg located in

{my_project_path}/public/images/flower.jpg

Here we have 3 ways to apply the basePath in your Image component:

  1. Hard-coding

    import Head from 'next/head';
    import styles from '../styles/Home.module.css';
    import Link from 'next/link';
    import Image from 'next/image'; 
    
    export default function Home() {
        return (
            <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <Image
                src='/absproxy/3000/images/flower.jpg'// Route of the image file
                height={144} // Desired size with correct aspect ratio
                width={144} // Desired size with correct aspect ratio
                alt="Your Name"
                />
            </main>
            </div>
        )
    }
    
  2. Import the image file as variable ({flower}):

import flower from '../public/images/flower.jpg'

then use as the Image[src] attribute:

    import Head from 'next/head';
    import styles from '../styles/Home.module.css';
    import Link from 'next/link';
    import Image from 'next/image';
    import flower from '../public/images/flower.jpg'
    export default function Home() {
        return (
            <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <Image
                src={flower}// Route of the image file
                height={144} // Desired size with correct aspect ratio
                width={144} // Desired size with correct aspect ratio
                alt="Your Name"
                />
            </main>
            </div>
        )
    }
  1. Import the

basePath

variable from next.config.js, and then concatenate the relative path of the static image file, and then apply in the src attribute of the image component.

src={${basePath}/images/flower.jpg}

        import Head from 'next/head';
    import styles from '../styles/Home.module.css';
    import Link from 'next/link';
    import Image from 'next/image';

    import { basePath } from '../next.config';

    export default function Home() {
        return (
            <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <Image
                src={`${basePath}/images/flower.jpg`}// Route of the image file
                height={144} // Desired size with correct aspect ratio
                width={144} // Desired size with correct aspect ratio
                alt="Your Name"
                />
            </main>
            </div>
        )
    }
Lunette answered 8/5, 2023 at 3:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.