9

I have a Next.js app I am deploying to Heroku. When I dev locally I see the images, but when I push to Heroku and check the site, the images have a 404. I have a public folder where I have the images (.png) right in the folder, and the code I reference the image like this

<Image
    src="/wb_blue_white.png"
    alt="WB Concept"
    width="70"
    height="70"
    className={navStyles.logo}
/>

Both locally and in prod the if I look at the image source they are the same src="/_next/image?url=%2Fwb_blue_white.png&w=256&q=75" but I get a 404 in prod. What could be causing the image to show up localhost but not in Heroku prod build?

package.json

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start -p $PORT"
},

file structure

components
pages
public
juliomalves
  • 42,130
  • 20
  • 150
  • 146
Chipe
  • 4,641
  • 10
  • 36
  • 64
  • How are you deploying to heroku? Maybe the server is blocking that traffic? – Hiro Mar 01 '21 at 18:56
  • @Hiro through the cli. I also have a favicon in that public folder that is working. Just the .png images are not – Chipe Mar 01 '21 at 19:06
  • What buildpack did you use? Probably auto detected as node app? then it seems like nextjs uses built-in(?) express server to serve content. In that case, is the express static serve configured? Like this: https://github.com/vercel/next.js/discussions/14121 – Hiro Mar 01 '21 at 19:17
  • @Hiro I was thinking it was something like that. I created the project using create-next-app which might use built in express server? I am not sure about that. Very new to next trying to learn it as I go along. So not sure where I would add the reference to use the path.join. I think next produces the server file when you build the project. – Chipe Mar 01 '21 at 20:24
  • added some (kinda) concrete instruction below. – Hiro Mar 03 '21 at 14:36
  • I am currently experiencing the same issue with firebase hosting at the moment Have you been able to find a solution to this issue? – vincent O Apr 12 '21 at 01:04
  • I am experiencing this issue even when I try to run in local system using next start it still doesn' load – Shivam Sahil Jan 21 '22 at 05:29
  • Any resolutions on this guys? – Shivam Sahil Jan 30 '22 at 16:17

5 Answers5

1

I was having this same problem. For me the issue was not the components at all. I was hosting my site on Netlify, and I didn't realize that by default Netlify builds the devDependencies. So node packages for development/testing were accidentally getting compiled for production.

I changed the NODE_ENV (in Netlify) to production and reorganized the packages between dependencies and devDependencies... and the error went away.

I think that the components triggered this issue because the initial request(s) cause them to be generated/optimized server-side. So even though the build succeeded. The remote image request caused dev packages to run in the wrong context.

I hope this someday helps someone else.

emersonthis
  • 32,822
  • 59
  • 210
  • 375
  • I still didn't understand what you said. For me when running `yarn start` after `yarn build` images are disappearing – Shivam Sahil Jan 21 '22 at 06:51
  • If this only happens when you run `build` but not when you run `yarn dev` then it might be the same problem. I _think_ that `build` only bundles the packages under `dependencies` but not `devDependencies`. I'm not a nextjs expert, but as a temporary quick test you could try moving all your devDependencies into dependencies and test if that works. (This is just for testing. Not a great solution for production) – emersonthis Jan 21 '22 at 23:41
  • Hmm even if it works but bundling up dev dependencies for production isn't a good thing right? – Shivam Sahil Jan 22 '22 at 06:26
  • > as a temporary quick test... (This is just for testing. Not a great solution for production) – emersonthis Jan 23 '22 at 08:11
0

Check out next custom server doc and its example repo.

Here in this express-looking code that's used to configure the server, app.render() seems to be setting routes for nextjs page, i.e. /a to pages/a. I'm not sure if that's even needed for each path or done for demo purpose. Try fiddling around.

Anyway, if it's anything like basic express server, which I suspect, use() method on express instance will add a "middleware", which 1. takes the request and 2. passes it to next middleware, or sends the response to client.

With server.use(express.static(path.join(__dirname, 'public')));, where server is the express instance in this case and fortunately(convention actually) in the example repo as well, you can add the middleware that handles static files serve.

I've forgotten the exact way of configuring express, but i'm guessing either:

  • right after the express() instantiation, or
  • right before the listen()

should do the trick. Just put server.use(express.static(path.join(__dirname, 'public'))) in there.

Hiro
  • 199
  • 1
  • 10
0

Create a directory for images in the root folder and import, relatively, from there. Does the trick.

skyridertk
  • 103
  • 1
  • 8
0

There are several articles on this, but basically Sharp is required and should be installed. The wording in the NextJS docs makes it sound optional, but with the default loader, Sharp is required.

AppsBeyond
  • 51
  • 1
0

In my case I had public folder in .dockerignore and all static assets were ignored as the result. Hope it might help someone.

Ruslan Kazakov
  • 433
  • 5
  • 4