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

adesurirey
  • 2,549
  • 2
  • 16
  • 36

5 Answers5

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
Daniel
  • 4,051
  • 2
  • 28
  • 46
  • 2
    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. – Logic Artist May 02 '18 at 18:21
  • I was able to implement this solution without adding `app/assets` to the `resolved_paths` – Fabrizio Bertoglio Dec 12 '18 at 08:59
  • What is line 11? Could you update this to show the entire file? – wuliwong Apr 03 '19 at 21:49
  • 1
    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. – David Hersey Apr 07 '20 at 15:31
  • If you use this method and also call the image from image_tag in your view, then your image is loaded twice – Edward Jun 10 '20 at 19:30
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.

Community
  • 1
  • 1
Srikanth V
  • 229
  • 3
  • 5
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

yohanes
  • 2,365
  • 1
  • 15
  • 24
0

Maybe this helps: https://engineering.klarna.com/migrating-from-rails-asset-pipeline-to-node-s-webpack-684230e3a93a Have a look at the Images part.

Smek
  • 1,158
  • 11
  • 33
  • Thanks a lot, you made my day. This was even more simple than said in the article you shared. All I had to do is install file-loader with `yarn install file-loader` then require my images `import Logo from '../../../assets/images/logo.png';` and user it `Logo`. that's great. – adesurirey Oct 20 '17 at 08:25
  • `install` has been replaced with `add` to add new dependencies. Run "yarn add file-loader" instead. – Manish Aug 16 '18 at 08:29
-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.

cfarina512
  • 15
  • 3
  • 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. – dkimot Apr 05 '21 at 20:35