-
Notifications
You must be signed in to change notification settings - Fork 72
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 #91
Comments
If someone else lands here with a similar problem. Here's how I've approached the issue. The following solution works with Webpacker, whether the dev server is running or the assets have been compiled to my public/ directory. InlineSvg allows for creation of custom asset finders so that's what this does. I'm fairly certain there may be a cleaner way to do this, but this works. # In config/initializers/inline_svg.rb
class WebpackerAssetFinder
class FoundAsset
attr_reader :path
def initialize(path)
@path = path
end
def pathname
if Webpacker.dev_server.running?
# The dev server is running. Load the SVG into a Tempfile.
asset = open("#{Webpacker.dev_server.protocol}://#{Webpacker.dev_server.host_with_port}#{path}")
tempfile = Tempfile.new(path)
tempfile.binmode
tempfile.write(asset.read)
tempfile.rewind
tempfile
else
# The dev server isn't running. The asset will be compiled to public.
Rails.application.root.join 'public', path.gsub(/\A\//, '')
end
end
end
def find_asset(filename)
if webpack_asset_path = Webpacker.manifest.lookup(filename)
return FoundAsset.new(webpack_asset_path)
end
end
end
# Override the Sprockets asset finder.
InlineSvg.configuration.asset_finder = WebpackerAssetFinder.new |
@moxie thanks for posting that solution, it seems like a perfect use of the custom asset finder. ✨ It seems the problem is related to the fact that Webpacker assets are served from a separate server in development mode. I guess another solution would be to only use your custom asset finder in Rails' development mode. I'm going to close this out for now. |
I also ran into this. To get around it I had to make some changes to the solution @moxie posted above. First, ensure you don't use The next issue I had (likely because I have some nested paths), is that the creation of the Lastly, since I depend on both webpacker and the asset pipeline, I ended up with a fallback approach. Here's what I ended up with: class WebpackerAssetFinder
class FoundAsset
attr_reader :path
def initialize(path)
@path = path
end
def pathname
if Webpacker.dev_server.running?
asset = open(webpacker_dev_server_url)
begin
tempfile = Tempfile.new(path)
tempfile.binmode
tempfile.write(asset.read)
tempfile.rewind
tempfile
rescue StandardError => e
Rails.logger.error "Error creating tempfile: #{e}"
raise
end
else
Rails.application.root.join("public", path.gsub(/\A\//, ""))
end
end
private
def webpacker_dev_server_url
"#{Webpacker.dev_server.protocol}://#{Webpacker.dev_server.host_with_port}#{path}"
end
end
def find_asset(filename)
if webpack_asset_path = Webpacker.manifest.lookup(filename)
FoundAsset.new(webpack_asset_path)
end
end
end Then in the class FallbackAssetFinder
attr_reader :finders
def initialize(finders)
@finders = finders
end
def find_asset(filename)
# try each finder, in order, return the first path found
finders.lazy.map { |f| f.find_asset(filename) }.find { |x| x != nil }
end
end
# Some of our SVG assets will be in the asset pipeline, some from webpacker,
# This allows us to find the SVGs for inlining in both cases.
InlineSvg.configuration.asset_finder = FallbackAssetFinder.new([
WebpackerAssetFinder.new,
InlineSvg::StaticAssetFinder,
]) Hope this helps someone else trying to do the same thing. Thanks to @moxie for providing the basis for this workaround. |
Since upgrading to Rails 6.0 RC1, neither @moxie or @subdigital solutions work. Not entirely sure why either. |
Added support for Webpacker in v1.5.0. |
Webpacker is "opt-in" as of v1.5.2 because it was breaking users that were using both Sprockets with precompiled assets and Webpacker: #98 (comment) |
In case anyone comes across this, I've been fighting this config today and was able to get it working finally for Rail v6.0.0. The general idea of the previous exmples works, but I had to adapt it in two ways:
|
Seeing as a lot of other people have looked into this, I figured I might as well tack on my own solution. It seems like the inline_svg implementation of the webpack svg resolver is similar to many of the examples here, so this is all it took for me to get it working properly in my own setup: class AppWebpackAssetFinder < InlineSvg::WebpackAssetFinder
def initialize(filename)
super(filename)
@asset_path = Webpacker.manifest.lookup("media/svg/#{@filename}")
end
end
class FallbackAssetFinder
attr_reader :finders
def initialize(finders)
@finders = finders
end
def find_asset(filename)
# try each finder, in order, return the first path found
finders.lazy.map { |f| f.find_asset(filename) }.find { |x| x != nil }
end
end
# Some of our SVG assets will be in the asset pipeline, some from webpacker,
# This allows us to find the SVGs for inlining in both cases.
InlineSvg.configuration.asset_finder = FallbackAssetFinder.new([
AppWebpackAssetFinder,
InlineSvg::StaticAssetFinder,
]) |
Looks like this gem struggles to handle files served from Rails Webpacker?
I have this inline
<%= inline_svg("#{asset_pack_path('images/grapes.svg')}") %>
But it results in a no asset found error.
When I actually visit the path, the image is there. I'll take a look and see if I can do a PR on this.
The text was updated successfully, but these errors were encountered: