Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpacker 4.0.0.rc2: images are not accessible from rails views #1839

Closed
deepj opened this issue Dec 18, 2018 · 17 comments
Closed

webpacker 4.0.0.rc2: images are not accessible from rails views #1839

deepj opened this issue Dec 18, 2018 · 17 comments
Labels
file loaders file-loader, fonts, images etc.

Comments

@deepj
Copy link
Contributor

deepj commented Dec 18, 2018

Hello,
I've made a fresh webpacker 4.0.0.rc2 installation and I'm trying to load an image from assets in a rails view

<%= image_pack_tag 'test.jpg' %>

The image is located in multiple paths (app/assets/images/test.jpg, app/javascript/images/test.jpg))

I don't see the file would be in the manifest

{
  "application.js": "/packs/application-8cac6ff83dcd20565aa4.js",
  "application.js.map": "/packs/application-8cac6ff83dcd20565aa4.js.map",
  "entrypoints": {
    "application": {
      "js": [
        "/packs/application-8cac6ff83dcd20565aa4.js"
      ],
      "js.map": [
        "/packs/application-8cac6ff83dcd20565aa4.js.map"
      ]
    },
    "hello_vue": {
      "js": [
        "/packs/hello_vue-e8868d6621d6bbe8029c.js"
      ],
      "js.map": [
        "/packs/hello_vue-e8868d6621d6bbe8029c.js.map"
      ]
    }
  },
  "hello_vue.js": "/packs/hello_vue-e8868d6621d6bbe8029c.js",
  "hello_vue.js.map": "/packs/hello_vue-e8868d6621d6bbe8029c.js.map"
}

I though, webpacker 4.0.0rc2 has out-of-box solution for this simple use case. I won't really import the image in application.js. I'd like to use it in the same way as using sprocket.

@gauravtiwari
Copy link
Member

@deepj What happens if you put your images under packs folder?

@deepj
Copy link
Contributor Author

deepj commented Dec 18, 2018

@gauravtiwari Unfortunately, without luck.

But the manifesto looks now (the location of image is app/javascript/packs/images/test.jpg)

{
  "application.js": "/packs/application-8cac6ff83dcd20565aa4.js",
  "application.js.map": "/packs/application-8cac6ff83dcd20565aa4.js.map",
  "entrypoints": {
    "application": {
      "js": [
        "/packs/application-8cac6ff83dcd20565aa4.js"
      ],
      "js.map": [
        "/packs/application-8cac6ff83dcd20565aa4.js.map"
      ]
    },
    "hello_vue": {
      "js": [
        "/packs/hello_vue-e8868d6621d6bbe8029c.js"
      ],
      "js.map": [
        "/packs/hello_vue-e8868d6621d6bbe8029c.js.map"
      ]
    },
    "images/test": {
      "js": [
        "/packs/images/test-386cb1dac0338a7cd384.js"
      ],
      "js.map": [
        "/packs/images/test-386cb1dac0338a7cd384.js.map"
      ]
    }
  },
  "hello_vue.js": "/packs/hello_vue-e8868d6621d6bbe8029c.js",
  "hello_vue.js.map": "/packs/hello_vue-e8868d6621d6bbe8029c.js.map",
  "images/test.js": "/packs/images/test-386cb1dac0338a7cd384.js",
  "images/test.js.map": "/packs/images/test-386cb1dac0338a7cd384.js.map",
  "packs/images/test.jpg": "/packs/packs/images/test-7a25cb51be37d1334cf2274ba9194279.jpg"
}

@gauravtiwari
Copy link
Member

What happens if you do this? Is this an image? test.js? should be test.jpg right?

try this
<img src="<%= image_pack_tag 'packs/images/test.jpg' %>" />

@deepj
Copy link
Contributor Author

deepj commented Dec 18, 2018

@gauravtiwari Hm, it works. It generates the following path

<img src="/packs/packs/images/test-7a25cb51be37d1334cf2274ba9194279.jpg" />

There is no test.js in my files, but it comes from webpacker and it's meant app/javascript/images/test.jpg I guess.

Here is my current file structure:

screenshot 2018-12-18 at 13 15 18

@grk
Copy link
Contributor

grk commented Dec 18, 2018

Can confirm, asset_pack_path needs the path to be packs/images/example.jpg to load from app/javascript/packs/images/example.jpg on 4.0.0.rc.2

@gauravtiwari
Copy link
Member

gauravtiwari commented Dec 18, 2018

What happens if you do this in application.js?

// top of packs/application.js
const importAll = (r) => r.keys().map(r)
importAll(require.context('../images', false, /\.(png|jpe?g|svg)$/));

This will load all images from images folder and then it should be available in manifest for you to pick up using asset_pack_path

@gauravtiwari
Copy link
Member

The images folder should be outside packs folder.

@grk
Copy link
Contributor

grk commented Dec 18, 2018

With importAll it works.

@gauravtiwari
Copy link
Member

Great, thanks @grk

Like mentioned in the README, everything must go through packs (entrypoint) for it to be available in the end. If you want a bunch of images to be available in the view, best to use importAll and then include it in the main pack and it should be available for you using asset_pack_path. Otherwise, you must require an image or another asset in the pack for it to be available in the view using helper tags.

We don't recommend putting anything other than js a.k.a packs inside packs folder, in other words, a JS package you are going to include in your view.

@deepj
Copy link
Contributor Author

deepj commented Dec 18, 2018

@gauravtiwari It works with importAll. But I still think this is confusing over sprocket. After reading webpacker 4.0.0 changelog, I thought this will work out-of-box. I believe many people will have a problem with this. What I post here, it's a common use-case. And if webpacker is a replacement for sprocket and a default in rails 6.0, this will be a source of many difficulties for many.

I believe, webpacker would support the above mentioned behaviour out-of-box and support just putting any images into app/assets/images and make them accessible via image_tag/image_pack_tag/asset_.... in rails views without any need to set something somewhere by default.

Importing them via "application.js" in some cases doesn't make sense in my point of view. Anyway, the current situation brings a lot complexity and make a simple thing much more harder.

I wish there would be some option in config/webpackeryml to set (disable if someone wants to) automatic loading images from app/assets/images into manifesto at least.

These are my thoughts about this topic

@jasl
Copy link
Contributor

jasl commented Jan 26, 2019

I believe that's relates to #1887

@gauravtiwari has made a fix, but document has a tiny bug need to be fixed.

For my experience, < rc.3 (above I didn't test) you can move your images into app/packs/images, then you can use your importAll("images") (actually I do the same thing like you), and in your view, you can ref them like this: <%= image_pack_tag("images/avatar.png") %> or you can check manifest json to prove it correction.

@jasl
Copy link
Contributor

jasl commented Jan 26, 2019

If you do this, you can remove sprockets, because Webpacker take care all frontend resources, but if you don't know Rails too much, I recommends you keep sprockets, and don't place resources which handled by Webpacker into app/assets

@deepj
Copy link
Contributor Author

deepj commented Jan 26, 2019

@jasl thanks, but you don't fully understand my issues. No, I don't use sprockets at all. I recommend you re-read this issue. If some changes have been made since this issue was reported, then it's good.

@guillaumebriday
Copy link
Member

guillaumebriday commented Feb 19, 2019

hey @deepj,

Does it work for you if your images are in a subfolder like so :

app/javascript/images/blog/thumbnail.jpg ?

Because it does not work for me, even with the @gauravtiwari's importAll hack :/

It only works for images at the root of images folder

My importAll method :

const importAll = (r) => r.keys().map(r)
importAll(require.context('../images', true, /\.(png|jpe?g|svg)$/))

EDIT: I only tried on 4.0.0.rc7

EDIT 2 :

I figured out why it does not work. It does import the images even in subfolders but with a wrong path in the manifest. It's because of the rc6 changes https://github.com/rails/webpacker/blob/master/CHANGELOG.md#400rc6---2019-01-25

The path are now /media/{whatever}.png in the manifest even for images in subfolders. More over, if multiples images have the same name in different subfolder, it takes only the latest one

@vidurpunj
Copy link

vidurpunj commented Jul 23, 2020

Inside the js file:
require.context('../images', false);
or
require.context('../images', false, /\.(png|jpe?g|svg)$/);

@digaoddc
Copy link

digaoddc commented Oct 1, 2020

For me, the solution was to add this line require.context('../images', true) in the file app/javascript/packs/application.js.

After that, I was able to use the image_pack_tag in the views

@guillaumebriday
Copy link
Member

Yes,
It’s in the docs now : https://github.com/rails/webpacker/blob/master/docs/assets.md

We can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
file loaders file-loader, fonts, images etc.
Projects
None yet
Development

No branches or pull requests

8 participants