我被困在宝石wicked_pdf上。
- 我正在生成一个pdf报告,我想包括样式表。
- 样式表是通过带有顺风的webpack生成的。
wicked_pdf文档中,据说我可以使用wicked_pdf_stylesheet_pack_tag
和wicked_pdf_javascript_pack_tag
来包含来自 webpack 的样式表和 javascript,但没有任何效果。
以下是来自控制器的代码:
format.pdf do
render template: "pdf_reports/show",
layout: "wicked_layout",
pdf: "report"
end
以下是布局中的代码:
<!DOCTYPE html>
<html>
<head>
<%= csrf_meta_tags %>
<%= wicked_pdf_javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= wicked_pdf_stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= wicked_pdf_stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
以下是视图pdf.erb中的代码:
<h1 class="text-red-base">Test pdf</h1>
<h2 class="test-wicked">mldgmdjgfd</h2>
它适用于wicked_pdf_stylesheet_link_tag(从链轮应用测试邪恶:文本为蓝色)但不适用于wicked_pdf_stylesheet_pack_tag(h1 应该是红色但不是)。
知道发生了什么吗?
谢谢!
分析
webpack 帮助程序做出了一些假设,这些假设可能不会在每个项目中都成立。
它们产生两种不同的结果,具体取决于running_in_develpment回报。对于 webpacker 3.0.0 或更高版本,此方法委托给Webpacker.dev_server.running?
。
如果没有运行开发服务器,帮助程序将假定资产已预编译,并尝试将资产的内容粘贴到<style>
或<script>
标记中。 如果资产在生产环境中预编译,并且在运行应用程序的环境的文件系统中可用,则这应该有效。这通常是正确的。
在运行开发服务器的情况下,webpack 帮助程序将返回一个标记,其中包含包资产的资产路径(最终使用标准asset_path
助手)。实际路径取决于导轨配置。在某些情况下,路径将与wkhtmltopdf
从file://...
呈现的html不兼容:
-
如果未设置
config.action_controller.asset_host
,则asset_path
将生成相对路径。这些在从文件wkhtmltopdf
渲染时不起作用。 -
如果设置了
config.action_controller.asset_host
,则在整个应用程序中将使用绝对URL(这是控制asset_path
返回内容的常规设置)。现在,如果资产在可以解析和访问资产主机的环境中运行,wkhtmltopdf
可能能够获取资产。在容器化应用程序中可能并非如此。
其他限制
在我们的例子中,我们有一些额外的约束:
-
我们的 PDF 发射动作支持一个参数,使它们
show_as_html: true
传递给render
。这使得wicked_pdf
跳过PDF生成并返回中间HTML。我们使用它来调试浏览器中的 HTML 视图。此 html 将由开发人员的浏览器在与运行wkhtmltopdf
不同的环境中呈现。 -
我们的开发设置是单线程的,因为我们使用调试器
better_errors
它依赖于同一应用程序实例提供的所有请求。另一方面,我们在请求中呈现PDF。这意味着wkhtmltopdf
将无法从应用程序请求资产(例如,通过将host: "localhost:3000"
传递给asset_path
),因为它已经占用了唯一可用的线程。
示例解决方案
我们的解决方案是实施我们自己的助手,这些助手更了解我们的设置。
在生产中,默认行为与我们的设置兼容,因此我们委托给原始行为,它将在文件系统中找到资产并将它们包含在生成的 HTML 中。
在开发中,在生成 PDF 时,我们将 webpack 开发服务器的主机名/端口传递给 webpacker 标签助手(这会将它们传递给
asset_path
)。开发服务器在单独的进程中运行,因此即使应用程序位于请求处理程序内,也会进行回放。在开发中,当返回中间 HTML(由我们的自定义帮助程序
show_as_html?
确定)时,不要将host:
传递给asset_pack_url
,这将导致"正常"的资产路径,就像在应用程序的其余部分一样,这将在浏览器中工作。
module PdfHelper
def pdf_stylesheet_pack_tag(source)
if running_in_development?
options = { media: "all" }
wds = Webpacker.dev_server
options[:host] = "#{wds.host}:#{wds.port}" unless show_as_html?
stylesheet_pack_tag(source, options)
else
wicked_pdf_stylesheet_pack_tag(source)
end
end
def pdf_javascript_pack_tag(source)
if running_in_development?
options = {}
wds = Webpacker.dev_server
options[:host] = "#{wds.host}:#{wds.port}" unless show_as_html?
javascript_pack_tag(source, options)
else
wicked_pdf_javascript_pack_tag(source)
end
end
end
在 pdf 布局中(苗条)
html
head
...
= pdf_stylesheet_pack_tag "pdf"
= pdf_javascript_pack_tag "pdf"
...