5

I am using the NextJS Image component like this:

<Image src="https://firebasestorage.googleapis.com/v0/b/africatech-7cf1b.appspot.com/o/images%2F1606851317444_impact-logo-sq-Owen-Hancock.png?alt=media&token=35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb" layout="fill" />

Locally it works and in the DOM it looks like this:

<img alt="Company logo" src="/_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=3840&amp;q=75" decoding="async" sizes="(max-width: 640px) 640px, (max-width: 750px) 750px, (max-width: 828px) 828px, (max-width: 1080px) 1080px, (max-width: 1200px) 1200px, (max-width: 1920px) 1920px, (max-width: 2048px) 2048px, 3840px" srcset="/_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=640&amp;q=75 640w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=750&amp;q=75 750w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=828&amp;q=75 828w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=1080&amp;q=75 1080w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=1200&amp;q=75 1200w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=1920&amp;q=75 1920w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=2048&amp;q=75 2048w, /_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&amp;w=3840&amp;q=75 3840w" style="visibility: visible; position: absolute; top: 0px; left: 0px; bottom: 0px; right: 0px; box-sizing: border-box; padding: 0px; border: none; margin: auto; display: block; width: 0px; height: 0px; min-width: 100%; max-width: 100%; min-height: 100%; max-height: 100%;">

However, on production it does not load the image. There is a 400 message:

GET https://launchafrica.io/_next/image?url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fafricatech-7cf1b.appspot.com%2Fo%2Fimages%252F1606851317444_impact-logo-sq-Owen-Hancock.png%3Falt%3Dmedia%26token%3D35afb1d8-4ab8-4f58-81b4-dd25e1f5f3eb&w=1920&q=75 400

Which seems to be because of: "url" parameter is not allowed

In my next.config.js I have this configured:

images: { domains: ['firebasestorage.googleapis.com'], },

Could someone assist me in figuring out how to use next/image with a Firebase storage hosted image in production? As locally it loads fine.

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
strangeQuirks
  • 4,761
  • 9
  • 40
  • 67

5 Answers5

1

Any chance you're hosting this on Firebase Hosting as well? I had this issue, and I realized that I had to import the next.config.js into the configuration while initializing NextJS:

const customNextConfig = require('./next.config');

const server = next({
  dev: isDev,
  conf: customNextConfig,
});

...
dohpahmine
  • 11
  • 1
  • Hmm for me its defined like `const nextjsDistDir = join('src', require('./src/next.config.js').distDir); const nextjsServer = next({ dev: isDev, conf: { distDir: nextjsDistDir, }, });` so maybe thats the issue – strangeQuirks Feb 26 '21 at 23:09
1

You need to add the below code on your next.config.js:

...
images: {
    domains: ['firebasestorage.googleapis.com'],
},
...
MsizaCodes
  • 41
  • 1
0

I'm late for the topic, but hope my answer will help someone else.

Adding the domain's config into the next.config.js is not enough, you need to make sure that your "next" instance grabs that config.

So in my case, what I did to make it work is:

Before

const nextjsDistDir = join("src", require("./src/next.config.js").distDir);
const nextjsServer = next({
  dev: isDev,
  conf: {
    distDir: nextjsDistDir
  }
});

After

const nextjsDistDir = join("src", require("./src/next.config.js").distDir);
const nextjsServer = next({
  dev: isDev,
  conf: {
    distDir: nextjsDistDir,
    images: {
      domains: ['firebasestorage.googleapis.com'],
    }
  }
});
doannx
  • 1,250
  • 13
  • 19
0

Leaving this here for posterity (as of 2021/12/21): this appears to be because NextJS (when started using npm start) doesn't actually use the next.config.js file. Looking at https://github.com/vercel/next.js/blob/canary/packages/next/cli/next-start.ts#L61, only the project directory, hostname and port are passed in to https://github.com/vercel/next.js/blob/canary/packages/next/server/lib/start-server.ts#L44. Because the conf parameter is not passed in, the images.domains is missing.

I ended up having to write my own (based on https://github.com/vercel/next.js/blob/canary/examples/custom-server-express/server.js):

const port = parseInt(process.env.PORT, 10) || 5000
const listen = process.env.LISTEN_INTERFACE || '127.0.0.1';
const dev = process.env.NODE_ENV !== 'production';
const app = next({
    dev: dev,
    customServer: false,
    hostname: process.env.HOSTNAME || 'localhost',
    conf: {
        images: {
            domains: [process.env.NEXT_PUBLIC_IMAGE_DOMAIN]
        },
        trailingSlash: true,
    poweredByHeader: false
    }
})
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const container = express();
    
  container.all('*', (req, res) => {
    return handle(req, res)
  })
    
    const server = http.createServer(container);
  server.listen(port, listen);
});
Femi
  • 64,273
  • 8
  • 118
  • 148
0

my problem solved with

images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**',
      },
    ],
  },