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

Created on 18 Dec 2018  路  17Comments  路  Source: rails/webpacker

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.

file loaders

Most helpful comment

@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

All 17 comments

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

@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"
}

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' %>" />

@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

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

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

The images folder should be outside packs folder.

With importAll it works.

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.

@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

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.

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

@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.

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

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

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

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

We can close this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ilrock picture ilrock  路  3Comments

ijdickinson picture ijdickinson  路  3Comments

pioz picture pioz  路  3Comments

Eearslya picture Eearslya  路  3Comments

christianrojas picture christianrojas  路  3Comments