0

I have a simple react app deployed on Heroku, (using the static-build pack https://github.com/heroku/heroku-buildpack-static) however the images are not loading. I know this must have to do something with the path, as it works for me locally, however nothing I have tried works.

Here is what the directory looks like

build
  index.html
  bundle.js
node_modules
public
  images
    logo.png
    index.html
src
    components
        LeftSidebar
            index.js
static.json
webpack.config.js

Here is my static.json file:

{
  "root": "build",
  "routes": {
    "/**": "index.html"
  },
  "https_only": true
}

I have set the image src (jsx in the LeftSidebar component) to have a relative path from the build to the public directory. The relative path from the build folder to the public folder like so:

"../public/images/logo.png"

The reason I did the above, is because I figured that since the only thing that is actually being ran in the browser is the index.html file which loads the bundle.js, which is invoking the <img /> this relative path would work. (please correct me if I'm wrong here)

I have also tried setting the path such that it is relative from my specific component LeftSidebar -- index.js to the image in the public folder:

../../../public/images/logo.png

I have also tried

public/images/logo.png

and a few other variations, all with no luck.

I think that I must be missing something more important about the way a static web server (Nginx in this case) will server static assets. Or int he way Webpack ultimately creates the bundle.js file.

It is also quite odd that there is no 404 status code returning, but the image won't load and the response in the network tab is nothing but a white screen.

JohnSnow
  • 444
  • 4
  • 17

1 Answers1

0

When importing images into React, we usually rely on Webpack to copy the appropriate files over, rather than having to reference a public directory, e.g.

src
    components
        MyComponent
            index.jsx
            image.png

In my index.jsx file, I'd simply import the image like so:

import myImage from './image.png';

Finally, and most importantly, you need to update your Webpack config to include a loader for your images if doesn't already include one, such as file-loader.

See this question/answer for more details on the process: How to import image (.svg, .png ) in a React Component

tombraider
  • 1,127
  • 1
  • 11
  • 19
  • So this would mean that for every single image i would need to do and import statement ? Also this doesn't explain why this is working on locally. – JohnSnow Jan 22 '19 at 08:50
  • Indeed, that's generally how we work with locally hosted images in React. See the `create-react-app` documentation for confirmation: https://facebook.github.io/create-react-app/docs/adding-images-fonts-and-files. When running your application locally, you are using webpack-dev-server, which differs from the production build. Generally, your webpack dev config differs quite greatly from your production config as production will include optimisation tasks. – tombraider Jan 22 '19 at 08:53
  • That seems kind of inefficient. That would mean that I have to use a relative path to the image regardless of nesting/sub-directories from my import statement. Thanks for the option, but i do believe there must be the more efficient way of resolving a public path where all images reside. With regards to locally, it also works if I just run my index.html file in the browser -- no webpack-dev-server – JohnSnow Jan 22 '19 at 09:10
  • Actually, it's incredibly efficient from a React/Webpack point-of-view as it will convert the image to a data URI, therefore reducing the number of requests that your user's browser needs to make. You can still have a single, top-level directory with all your images if you wish, they don't necessarily have to be in a component directory. Obviously the choice is yours, but this is the way React was designed. – tombraider Jan 22 '19 at 09:14
  • Right, I understand the data-uri efficiency. I want to have it as a top-level directory without the need to have to write a different relative path every-time. It is inefficient from a dev prespective. Any thoughts on how that could be achieved? – JohnSnow Jan 22 '19 at 09:18
  • Hmm, you could create a helper function that imports all of the images in a directory and then returns the appropriate image depending on what argument you use. I've done something similar for icon SVGs before using Webpack's context API: https://github.com/webpack/docs/wiki/context. – tombraider Jan 22 '19 at 09:30