Search code examples
next.jsfirebase-hosting

Next JS Firebase hosting html and data here but no stylesheet and some scripts have 404 ERROR


I am on a journey to deploy my first next app on firebase.... what a headache?! Somehow I managed to deploy it but now I am facing a bunch of issues.

I have styled my components with bootstrap and sass and I am fetching my images and data from an url/public api.

The page load with all the data but no styling and no pictures displayed. When I check the console there are a few errors related to some get requests that get 404 responses. Checking the network tab it shows that my css files have not loaded as well as some scripts.

I don't know what part of code to share as I just don't know what is wrong. I have added some screenshot of related issues, I hope this helps.

Can someone tell me what I should do?

thanks Leo [![console network tab][1]][css]

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

package.json

{
  "name": "crypto-react",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "axios": "^0.24.0",
    "bootstrap": "^5.1.3",
    "export": "^0.1.337",
    "next": "^12.0.4-canary.4",
    "next-compose-plugins": "^2.2.1",
    "next-optimized-images": "^2.6.2",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-icons": "^4.3.1",
    "sharp": "^0.29.2"
  },
  "devDependencies": {
    "eslint": "7.32.0",
    "eslint-config-next": "12.0.3"
  }
}

next.config.js

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



module.exports = {
  distDir: 'build',
  images: {
    domains: ['assets.coingecko.com'],
    loader: 'custom',
    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]',
            },
          },
        ],
      },
    ],
  },

  //...
}


Solution

  • 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 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 it :).

    Thank you all for your help. I hope this will someone in the future. :)