Skip to content
This repository has been archived by the owner on Oct 2, 2019. It is now read-only.

Loading images with rails helpers #61

Open
Matt-Butler opened this issue Sep 28, 2016 · 8 comments
Open

Loading images with rails helpers #61

Matt-Butler opened this issue Sep 28, 2016 · 8 comments

Comments

@Matt-Butler
Copy link

What is the recommended way of referencing images with webpack-rails?

Is it possible to use something like this?

= image_tag *webpack_asset_paths('my-image', extension: 'png')
@mipearson
Copy link
Owner

I don't know, to be honest. I haven't played with images in webpack. Give it a go and see!

@Matt-Butler
Copy link
Author

I think I understand the issue now. My images are not part of the assetsByChunkName attribute in the manifest.json file. This helper will not find my image assets: *webpack_asset_paths('file', extension: 'png')

manifest.json

  "assetsByChunkName":{
      "file":[
         "file-554ffb8dcc2a3d701ac2.js",
         "file.css"
      ]
   },

There are two potential options:

  1. Figure out how to add images to the assetsByChunkName attribute in manifest.json
  2. Find out how to push my assets onto the path variable
    paths = manifest["assetsByChunkName"][source]

@Matt-Butler
Copy link
Author

I found another work around by just making a css class for every image. I am also using the webpack url/file loader.

<div class="graphic" />
.graphic {
  background-image: url('./file.png');
  background-repeat: no-repeat;
  background-size: contain;
  width: 6rem;
  height: 6rem;
}

@jeffutter
Copy link

Did anyone find a way to use image tags yet? I'm not sure using classes is really a viable solution.

@schneidmaster
Copy link

I developed a fairly nice solution to this using Rails 4.1. (Should work on other Rails versions but the patches may vary.)

  1. Install the asset-map-webpack-plugin and add it to your webpack config.

  2. Somewhere in your JS, require all of the image assets that you want to reference in your Rails app with image_tags. I used an image manifest JS file that I required in from the entry file. (I don't love this step but I haven't thought of a better way to do it yet.)

  3. Create an initializer (something like config/initializers/image_assets.rb) and patch ActionView to reference the file generated by asset-map-webpack-plugin when resolving image paths. Here's what I wrote (may vary based on where you're putting your built assets):

module ActionView
  module Helpers
    module AssetUrlHelper
      def compute_asset_path(source, options = {})
        if options[:type] == :image
          asset_map[source]
        else
          dir = ASSET_PUBLIC_DIRECTORIES[options[:type]] || ""
          File.join(dir, source)
        end
      end

      private

      def asset_map
        return @asset_map if @asset_map

        translated = {}
        asset_manifest['assets'].each do |asset, mapped|
          # Only include image assets in the lookup hash.
          next unless asset.include?('app/assets/images')

          # Trim to ensure path matching is correct --
          # if image is at `app/assets/images/path/to/image.png`, 
          # we want to use `image_tag('path/to/image.png') as expected.
          asset_tail = asset.split('app/assets/images/').last
          translated[asset_tail] = mapped
        end
        if Rails.env.development?
          translated
        else
          @asset_map = translated
        end
      end

      def asset_manifest
        return @asset_manifest if @asset_manifest

        if Rails.env.development?
          host = ::Rails.configuration.webpack.dev_server.manifest_host
          port = ::Rails.configuration.webpack.dev_server.manifest_port
          http = Net::HTTP.new(host, port)
          http.use_ssl = ::Rails.configuration.webpack.dev_server.https
          http.verify_mode = OpenSSL::SSL::VERIFY_NONE
          JSON.parse(http.get('/assets/asset_map.json').body)
        else
          @asset_manifest = JSON.parse(File.read(Rails.root.join(Rails.configuration.webpack.output_dir, 'asset_map.json')))
        end
      end
    end
  end
end

I also had to patch asset-map-webpack-plugin to get it to work in development. The original version uses fs.writeFileSync to naively write out the asset json file, rather than adding it to the webpack output assets (and so in development it still tries to write out to the filesystem rather than storing/serving in memory from the dev server). I may send a PR to the original repo with my changes, or just publish my own package with more targeted configuration for this use case.

@mipearson, let me know if you think this approach is worth standardizing and including in webpack-rails itself. I can clean up my code and send a PR.

@pavels
Copy link

pavels commented Jan 17, 2017

I have accomplished the same thing with already existing stats plugin
here is my fork https://github.com/pavels/webpack-rails
it needs more refinement, but works ok

@jeffutter
Copy link

Any progress on this? We are running into the same issue.

@alexkrolick
Copy link
Contributor

Try using the url-loader helper and using JS import/requires:

https://gist.github.com/alexkrolick/cb120d2e0f8450f1cd49d175f7a66dfe#file-webpack-config-js-L54-L57

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants