How to handle images in a Rails / Webpacker / React app?
Asked Answered
Y

4

26

I am using Webpacker with rails 5.1.4 to play with React, Redux, and react-router-dom.

I have a Navbar.jsx component in app/javascript/src/components/ that needs to display an image, but I am not able to access my images stored in app/assets/images/.

Here is what I've tried :

<img src="logo.png" alt="Logo" />
<img src="assets/logo.png" alt="Logo" />
<img src="assets/images/logo.png" alt="Logo" />

From root path the last attempt works because /assets/images/logo.png does exist, but when I navigate to /posts/:id, it gives me the following error:

logo.png:1 GET http://localhost:3000/posts/assets/images/logo.png 404 (Not Found)

Can you help me? And more over what's your way to handle images in that kind or hybrid React/Rails app?

Thanks

Yeasty answered 20/10, 2017 at 7:46 Comment(0)
N
39

Just edit the file config/webpacker.yml and replace this line:

resolved_paths: []

with this this:

resolved_paths: ['app/assets']

Then, put the image in app/assets/images folder and load it like this:

import React from 'react'
import MyImage from 'images/my_image.svg'

const MyComponent = props => <img src={MyImage} />

export default MyComponent
Neary answered 30/10, 2017 at 7:57 Comment(5)
I have exactly the same scenario, and I have tried the above, however I continue to get the error that the image cannot be resolved.Upheaval
I was able to implement this solution without adding app/assets to the resolved_pathsChaffin
What is line 11? Could you update this to show the entire file?Mercurio
This worked for me with Rails 6 ... unlike responses below I needed to add 'app/assets' to resolve_paths. I imagine I'd have to do this for CSS as well if I wanted to use assets folder for that.Dewayne
If you use this method and also call the image from image_tag in your view, then your image is loaded twiceBobo
B
4
If we leave resolved_path as [] in webpacker.yml also it works.

Example = 

# Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  resolved_paths: []

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

You can even create an image folder in your components. Load it in the component file like below-

import React from 'react';
import MyImage from '${imagePath}/example1.png'

export class MyComponent extends React.Component {
  render() {
    return (
     <React.Fragment>
       <img src={MyImage} alt="Image text"/>
     </React.Fragment>     
    )
  }
}

WebPacker internally converts these image paths to packs.

Benton answered 11/4, 2019 at 13:38 Comment(0)
A
3

Update 2021 (rails 6.1.4), the resolved_paths key has changed into additional_paths.

So, change :

# config/webpacker.yml

default: &default
  resolved_paths: []

into:

# config/webpacker.yml

default: &default
  additional_paths: ['app/assets']

and the rest following Daniel's answer's

Analogy answered 23/8, 2021 at 8:49 Comment(0)
M
-1

For those who may still be having this issue, give this a try:

Put your img in app/assets/images. In this example my image is called 'logo.png'.

In your application.html.erb file, put this in the head:

<script type="text/javascript">
   window.logo = "<%= image_url('logo.png') %>"
</script>

Now in your component, render the image:

return (
  <div>
    <a href="/">
      <img src={window.logo}/>
    </a>
  </div>
);

Hope this helps.

Malaguena answered 30/7, 2019 at 1:38 Comment(1)
while this works it's bad practice to add to the window object in js. it makes unit testing more difficult, allows any script on the page to change your image which could open up xss vectors, and you would have to follow that process for every image you want.Midweek

© 2022 - 2024 — McMap. All rights reserved.