Webpacker: Loading images with the file-loader

Created on 25 Sep 2017  ยท  8Comments  ยท  Source: rails/webpacker

I've just upgraded an app from webpacker2 to 3 and am having new issues with some .png files that I'm referencing in my app.

One thing that doesn't appear to be an issue, but looks odd is the generated path of my image:

My image is in {Rails.root}/app/javascripts/packs/sample.png and when I import the image and references it in a template, the resulting path is /packs/packs/sample-{hash}.png. Why the extra packs in the path?

My main issue though is that I use asset_pack_path 'sample.png' and now get an error ActionView::Template::Error (Webpacker can't find sample.png in {app_path}/public/packs/manifest.json

And the manifest has the following entry for my image:

{
  ...
  "packs/sample.png": "/packs/packs/sample-9fca67443f10bc216cfd8ae755ab0dcc.png"
  ...
}

I'm not sure what the solution here is. This was working great in webpacker2. I noticed that the assets.js loader from webpacker2 and the file.js loader from webpacker3 are for the same thing, but have differing options for the name attribute:

webpacker2
name: env.NODE_ENV === 'production' ? '[name]-[hash].[ext]' : '[name].[ext]'
webpacker3
name: '[path][name]-[hash].[ext]'

I'm not sure if this is the cause of my issue?

Most helpful comment

@renchap Thank you, I was filnally able to display the image correctly. I was too focused on getting the right Webpacker configuration, that I missed the possibility that this was a Typescript error.

All 8 comments

The packs directory should only contain your Webpack entry points. Try to move all your other files out of it, for this image somewhere like {app_path}/app/javascripts/images/sample.png

@akaspick The images are now resolved relative to app/javascript so if you have a sub-directory inside app/javascript it will be preserved. Like @renchap suggested you could move all images outside of packs and put them inside images folder. Here is the PR for your reference: https://github.com/rails/webpacker/pull/695

All good now thanks.

Note for others; I moved my images and changed:

import sampleImg from './sample.png' to import sampleImg from 'images/sample.png'
asset_pack_path 'sample.png' to asset_pack_path 'images/sample.png'

Hi @akaspick can you please elaborate a little bit more on how you use an image inside your javascript files? I am havig trouble understanding how to use images from the javascript files.
My file structure:

โ”œโ”€โ”€ app/javascripts
โ”‚   โ”œโ”€โ”€ images
โ”‚   โ”‚       โ”œโ”€โ”€ sample.jpg
โ”‚   โ”œโ”€โ”€ my_app
โ”‚   โ”‚       โ”œโ”€โ”€ index.ts
โ”‚   โ””โ”€โ”€ packs
โ”‚           โ”œโ”€โ”€ my_app.js

If I import my image in packs/my_app.js like so:

// packs/my_app.js
import image from 'images/sample.jpg'

the code compiles without any error, but then when I try to use this image inside my app

// my_app/index.ts`
import image from 'images/sample.jpg'
//or import image from '../images/sample.jpg'

I receive an error in the compiler logs:
TS2307: Cannot find module 'images/sample.jpg'.

Any help would be appreciated.

@juandefelix Your example structure looks the same as mine. Did you add 'jpg' to your extensions in config/webpacker.yml?

Yes, it is there. This is my config/webpacker.yml file:

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_output_path: packs
  cache_path: tmp/cache/webpacker

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

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  extensions:
    - .erb
    - .tsx
    - .ts
    - .ts.erb
    - .js
    - .js.erb
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg
    - .html

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: /node_modules/


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Cache manifest.json for performance
  cache_manifest: true

also, the config/webpack/environment.js:

const webpack = require('webpack')
const { resolve } = require('path')
const { environment, config } = require('@rails/webpacker')
const typescript =  require('./loaders/typescript')

environment.plugins.append('ContextReplacement',
  new webpack.ContextReplacementPlugin(
    /angular(\\|\/)core(\\|\/)(@angular|esm5)/,
    resolve(config.source_path)
  )
)


environment.loaders.append('typescript', typescript)
module.exports = environment

@juandefelix This is a Typescript error, not a Webpack-related one.
It occurs because the TS compiler does not know what is a .jpg file and what type it should have.

You need to tell TS to load type informations from, for example, typings/index.d.ts (using "files": ["typings/index.d.ts"] in tsconfig.json), containing something like:

declare module "*.jpg" {
  const path: string;
  export default path;
}

This will make the TS compiler know that the default export for files matching *.jpg is a string (because this is what the file-loader is returning).

@renchap Thank you, I was filnally able to display the image correctly. I was too focused on getting the right Webpacker configuration, that I missed the possibility that this was a Typescript error.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

itay-grudev picture itay-grudev  ยท  3Comments

naps62 picture naps62  ยท  3Comments

suhomozgy-andrey picture suhomozgy-andrey  ยท  3Comments

inopinatus picture inopinatus  ยท  3Comments

vtno picture vtno  ยท  3Comments