mileszs / wicked_pdf

PDF generator (from HTML) plugin for Ruby on Rails
http://www.mileszs.com/wicked-pdf-plugin
MIT License
3.54k stars 646 forks source link

Wicked PDF with Webpack #745

Open damienlethiec opened 6 years ago

damienlethiec commented 6 years ago

Hello there,

I decided to remove the asset pipeline in my current app and use Webpack for all my assets (including css). How could I access my "Webpack CSS" from inside my Wicked PDF? Is there some kind of wicked_pdf_stylesheet_pack_tag helper? If not, what could be my options?

Thanks a ton in advance, Damien

unixmonkey commented 6 years ago

@LeKristapino has added a wicked_pdf_stylesheet_pack_tag in this PR: https://github.com/mileszs/wicked_pdf/pull/739/files

If you could help finish up that PR, or at least vouch for it working in your configuration, it would be appreciated, and will expedite getting it merged into a release version.

damienlethiec commented 6 years ago

Hi @unixmonkey. Thanks a ton for the answer, I missed the pull request.

I tried the solution proposed by @LeKristapino and it almost worked out of the box for me. Indeed, I only had to remove the following first part of the conditional:

if Webpacker.dev_server.running?
    stylesheet_pack_tag(*sources)
else

Apparently, rebuilding the source path and passing it to wicked_pdf_stylesheet_link_tag is the only working option for me. I will comment the PR.

Could you please link this issue to the PR so I get notified when the PR is merged?

Thanks a ton for everything! Damien

unixmonkey commented 6 years ago

Sure, I think this will do it: #739

damienlethiec commented 6 years ago

Perfect! Thanks :) Let me know if I can help more by testing something :)

LeKristapino commented 6 years ago

Sorry for the delay. I will update my PR to be ready for merge this week

LeKristapino commented 6 years ago

@damienlethiec I looked at the Webpacker code, and it seems weird that stylesheet_pack_tag(*sources) did not work for you in development mode.

This line suggests that the second part of the conditional would not work in development environment.

damienlethiec commented 6 years ago

@LeKristapino Could you explain me why? It looks to me that it is logical that it works in development but I am probably missing something.

damienlethiec commented 6 years ago

@LeKristapino BTW I tried your new commit and unfortunately still does not work for me in development (for the same reason) :(

LeKristapino commented 6 years ago

@damienlethiec What is your Webpacker version? I checked that the asset_pack_path implementation changes throughout versions. In other versions the conditional that I pointed to, is not yet implemented.

damienlethiec commented 6 years ago

Version 3.5.3

LeKristapino commented 6 years ago

@damienlethiec Could you provide the error message that you're getting?

damienlethiec commented 6 years ago

I don't get any error message. The pdf is generate normally but without any style. For info, I generate the pdf in background with the pdf_from_string method. Don't see what could be the impact but in case, here is my code:

class GeneratePdfJob < ApplicationJob
  queue_as :default

  def perform(briefing_id)
    @briefing = Briefing.find(briefing_id)
    set_view
    @template = "briefings/#{@briefing.underscored_class_name}s/show.pdf.erb"
    generate_pdf
  end

  private

  def set_view
    @view = ActionView::Base.new('app/views', {}, ActionController::Base.new)
    @view.class_eval do
      include WickedPdfHelper
      include ApplicationHelper
    end
  end

  def generate_pdf
    pdf = WickedPdf.new.pdf_from_string(
      @view.render(
        template: @template,
        locals: { '@briefing': @briefing },
        layout: 'layouts/pdf.html.erb'
      )
    )
    @briefing.pdf_summary.attach(io: StringIO.new(pdf), filename: "briefing##{@briefing.id}",
                                 content_type: 'application/pdf')
  end
end
LeKristapino commented 6 years ago

Hmm, I have a similar use case, but development environment seems to be working fine. One possible case might be that you don't include some helpers, but then it should probably raise some errors.

One off-topic suggestion though - In Rails 5.0 there is a thing called ApplicationController.renderer which relieves you from setting up rendering process the "dirty" way via initiating new ActionView and manually adding helpers. In my case I use it like this

renderer = ApplicationController.renderer.new
WickedPdf.new.pdf_from_string(
  renderer.render(
    layout: 'reports_pdf',
    template: 'pdf/reports/show.html.slim',
    assigns: {
      manager: @manager,
      data: @data,
    }
  ), 
  margin:  {
    top: 0,
    bottom: 0,
    left: 0,
    right: 0
  }
)

maybe you could try it this way, and see if the problem still exists.

damienlethiec commented 6 years ago

Oh, super cool, let me try!

damienlethiec commented 6 years ago

Thanks a ton for the tips. Unfortunately the helper still does not work. To be more precise:

1) When I keep the conditional (in the new as well as in the old code), the helper returns <link rel=\"stylesheet\" media=\"screen\" href=\"/packs/pdf-597c223875c75fe1d8b0e28fe1db199d.css\" /> which looks cool but does not generate any style in the PDF (I don't really get why)

2) When I remove the conditional from the new code, the helper returns <style type='text/css'></style> because defined?(Webpacker::VERSION) returns nil. This is probably because I test your code in an helper. Do you have another more intelligent option for me to try your new code, I am not sure I am doing it well.

LeKristapino commented 6 years ago
  1. It looks like you are not running a webpack dev server, because then the link would be prepended by http://localhost:8080, that seems to be the issue why you don't see any CSS. This should be fixed by checking for Webpacker.dev_server.running? as I do in the helper method. Check if there aren't any weird responses in that area.

  2. This seems very weird, given that Webpack definitely responds to ::VERSION. Check if 'webpack/version' is required (although it should be since it is required in the wicked pdf helper file)

damienlethiec commented 6 years ago
  1. I am running Webpacker dev server but I am running it from a procfile managed by Overmind (https://github.com/DarthSim/overmind).

I am sorry, I am a bit in a hurry right now. I will come back to all of this in a few days and do my best to find a solution! Sorry for this :/

martinbjeldbak commented 6 years ago

@damienlethiec I had a similar problem as you with stylesheets not loading, and fixed it by using full URLs instead of relative paths to the CSS/JS assets. I did this by setting config.action_controller.asset_host = "localhost:5000" in config/environments/development.rb (port 5000 is where I run the Rails server, not Webpacker).

This updated the path to stylesheets from e.g. /packs/pdf-1234.css to http://localhost:5000/packs/pdf-1234.css in the helpers, and solved the problem for me. Hope this helps!

cseelus commented 6 years ago

I have the same issue as @damienlethiec. Does not matter if I use absolute paths (by setting config.action_controller.asset_host) or not.

Whats strange is that everything seems ok if I render as HTML with show_as_html: true. As soon as I render as PDF, all styles are gone. Also tried not using Wicked PDF in a background process, to no avail.

Inlining the styles like wicked_pdf_stylesheet_link_tag does, might be the way to go, would also be more consistent imho.

ClareBee commented 5 years ago

Finally got it working by putting the pdf-specific scss file back into an assets/stylesheets folder rather than in packs, then adding resolved_paths: ['app/assets/stylesheets'] to my webpack.yml. This works for me with <%= wicked_pdf_stylesheet_link_tag "name_of_scss_file" %> in the head of the pdf.html.erb layout. Rest of the app uses scss loaded by webpack's stylesheet_pack_tag

cseelus commented 5 years ago

@ClareBee Isn't that approach just circumventing Webpacker and falling back to Sprockets? Using Sprockets hasn't been a problem with Wicked PDF.

zernie commented 5 years ago

@damienlethiec @ClareBee if you're on Webpacker 4, dont forget to turn on extract_css option.

jhirn commented 5 years ago

@martinbjeldbak 's solution to add asset_host solved this for me. Unfortunately, this won't work in production as the wkhtmltopdf executable won't be authenticated to retrieve the path via URL.

Previously we were embedding the stylesheet with the base64 helper but that doesn't seem to work with Webpacker assets. I'm not trying to open up public resources so for now I'm just going to embed the scss in the slim template itself or include as a partial so rails generates the full template for the wkhtmltopdf executable.

arabakevin commented 5 years ago

Hi, I've an issue when i use =wicked_pdf_stylesheet_link_tag and wicked_pdf_javascript_link_tag. Capture d’écran 2019-10-07 à 18 09 34 I've describe with more details in the ticket #858 Thanks in advance for your help.

yonnyquiceno commented 4 years ago

Hi,

I solved this by overriding the wicked_pdf_stylesheet_pack_tag, I created this one based on the actual gem code:

# app/helpers/wicked_pdf_assets.rb
module WickedPdfAssets
  def wicked_pdf_stylesheet_pack_tag(source)
    css_text = wicked_pdf_stylesheet_link_tag(webpacker_source_url("#{source}.css"))
    css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
  end
end

Then I invoke the helper in the controller using helper WickedPdfAssets, it takes precedence over the gem method and fixes the problem (at least for me)

Note: not tested in production.

dcangulo commented 3 years ago

Every solution here only works on development but not on staging and production at least for me.

What I did is based on @yonnyquiceno's comment with a little revision.

app/helpers/application_helper.rb

# frozen_string_literal: true

require 'open-uri'

module ApplicationHelper
  def wicked_pdf_stylesheet_pack_tag(source)
   css = URI.open(webpacker_source_url("#{source}.css")).read

   "<style>#{css}</style>".html_safe
  end
end

Not the best and secured workaround but works for me.

unixmonkey commented 3 years ago

@dcangulo Are you saying the solution you posted works in production, or are you saying it also has problems in production?

dcangulo commented 3 years ago

@unixmonkey

Haven't tested on production but works on staging with configuration almost the same with my production environment. The solution that I have come up with works in my staging environment.

The problem that I have is that wicked_pdf_stylesheet_pack_tag only works on development environment and returns a blank style tag <style type="text/css"></style> on staging.

My current stack are the following:

ruby '3.0.0'
gem 'rails', '~> 6.1.1'
gem 'webpacker', '~> 5.2'
gem 'wicked_pdf', '~> 2.1'
gem 'wkhtmltopdf-binary', '~> 0.12.6.5'