Search code examples
next.jsserver-side-renderingfirebase-hosting

How to set up Next image loader url correctly for external url


I am trying to host my first app on firebase and i am experiencing some issues with the image loader on next.config file. initial config is as below

module.exports = {
images: {
domains: ['assets.coingecko.com'],
loader: 'imgix',
path: 'https://assets.coingecko.com/coins/images/',
},

When i check the url on the deployed page the link direct to

https://assets.coingecko.com/https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579=&auto=format&fit=max&w=64

but the correct url be

https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579=&auto=format&fit=max&w=64.

i have tried to amend my config files to the following

module.exports = {
images: {
domains: ['assets.coingecko.com'],
loader: 'imgix',
path: '/',
},

or

module.exports = {
images: {
domains: ['assets.coingecko.com'],
loader: 'imgix',
path: '',
}, 

but when i do it and deploy the page again i receive errror 500 white page. Can someone help a rookie please? i don't know what to do with it.

full next.config.js snippet

const webpack = require('webpack');
const path = require('path');
//const withPlugins = require('next-compose-plugins');
//const optimizedImages = require('next-optimized-images');
//const withImages = require('next-images')


module.exports =  {
  images: {
    domains: ['assets.coingecko.com'],
      // loader: 'imgix',
      // path: '',
  },
  reactStrictMode: true,
  entry: './src/index.js',
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
  module: {
    rules: [
      //...
      {
        test: /\.(png|jp(e*)g|svg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: 'images/[hash]-[name].[ext]',
            },
          },
        ],
      },
    ],
  },

  //...
}

server.js

const { https } = require('firebase-functions');
const { default: next } = require('next');

const isDev = process.env.NODE_ENV !== 'production';

const server = next({
    dev: isDev,
    //location of .next generated after running -> yarn build
    conf: { distDir: '.next' },
    //images :{ domain :['assets.coingecko.com'],}
});

const nextjsHandle = server.getRequestHandler();
exports.nextServer = https.onRequest((req, res) => {
    return server.prepare()
        .then(() => {
            return nextjsHandle(req, res)
        });
});

Solution

  • Alright, so I manage to get around it @rawwater @SeanW.

    Basically what needed to be done in my case to remove the loader and the path from the next config page as follows:

    const webpack = require('webpack');
    const path = require('path');
    //const withPlugins = require('next-compose-plugins');
    //const optimizedImages = require('next-optimized-images');
    const withImages = require('next-images')
    
    
    module.exports = withImages(  {
      
      images: {
        domains: ['assets.coingecko.com', 'mywebsite.whatever.com'],
          //  loader: 'imgix',
          //  path: 'https://assets.coingecko.com/',
      },
    
      reactStrictMode: true,
      entry: './src/index.js',
      sassOptions: {
        includePaths: [path.join(__dirname, 'styles')],
      },
    
      module: {
        rules: [
          //...
          {
            test: /\.(png|jp(e*)g|svg|gif)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  name: 'images/[hash]-[name].[ext]',
                },
              },
            ],
          },
        ],
      },
    
      //...
    }
    )
    

    on the server.js uncomment images as follow:

    const { https } = require('firebase-functions');
    const { default: next } = require('next');
    
    const isDev = process.env.NODE_ENV !== 'production';
    
    const server = next({
        dev: isDev,
        //location of .next generated after running -> yarn build
        conf: { distDir: '.next' },
        //images :{ domain :['assets.coingecko.com'],}
    });
    
    const nextjsHandle = server.getRequestHandler();
    exports.nextServer = https.onRequest((req, res) => {
        return server.prepare()
            .then(() => {
                return nextjsHandle(req, res)
            });
    });
    

    Then add a custom loader to my image as follow on the component this is supposed to render them.

    
    const myLoader = ({ src, width, quality }) => {
      return `${src}?w=${width}&q=${quality || 75}`
    }
    
    <Image
      loader={myLoader}
      className="mr-3"
      src={image}
      alt="crypto"
      height={30}
      width={30}
    />
    
    

    And that's it.