For me it was fixed my waiting for network idle if I recall correctly. That or ignore https errors
Tailwind Styles in Broswershot made PDF
I've been trying to use the Spatie/Browsershot to convert blade views into PDFs. However, the PDF is not applying the tailwind classes. Does anyone have any pointers as to why this may be happening / how to correct this?
Thanks!
@Sinnbeck So far I've tried both methods, and still, the PDF comes without any styling whatsoever:
$html = view('PdfLayouts.driver-application', ['driver' => $driver])->render();
Browsershot::html($html)
->showBackground()
->waitUntilNetworkIdle()
->ignoreHttpsErrors()
->margins(5, 5, 5, 5)
->save(storage_path('test.pdf'));
Do you have any other ideas?
@undeportedmexican and if you just return it, it looks correct?
$html = view('PdfLayouts.driver-application', ['driver' => $driver])->render();
return $html;
@Sinnbeck Yes, I tested the exact same way you're suggested, and the page renders with all styles. This is annoying LOL
@undeportedmexican I remember having the exact same issue. Let me just check next time I get on my computer. Just in case it isn't related. What is your setup on dev (I assume this is dev)? How are you compiling? Mix?
@Sinnbeck I appreciate you checking.
I'm running my v-hosts in MAMP (not pro)
- Apache
- Php 7.4
- Laravel Mix 6.0.6
- Tailwind 3.0.12
This app is Laravel + Inertia + Vue. However, for this particular action I'm just using blade templates (I created an additional base layout, and am running the pdf-view through this additional layout that includes the CSS bundle, but not the JS bundle).
So if I pull in Tailwind through CDN, all the styles are applied correctly. This means there's an issue when loading the app.css file from my public directory. Any ideas as to why this may be happening?
So, I did a thing. Apparently, there's a setOption method, that allows you to pass options to the Puppeteer command, and apparently, you can send a 'style' tag to the Puppeteer browser. I managed to make it work like that, but I would like to get your opinion on the matter if possible.
Browsershot::html($html)
->waitUntilNetworkIdle()
->setOption('addStyleTag', json_encode(['path' => 'css/app.css']))
->margins(5, 5, 5, 5)
->save(storage_path('test.pdf'));
@undeportedmexican mine worked as expected by using style on the page. One thing you could try is to extract the content (though I believe it should work without that)
<style>
{{file_get_contents(public_path('css/app.css'))}}
</style>
@Sinnbeck It works like that too. I believe both ways are 'essentially' the same thing, in 2 different ways.
Either way, I appreciate your time on this. Bouncing the info back and forth was super useful.
Thanks man!
@undeportedmexican I'll see if I can figure out how I solved myself. I remember using the just posted method as a way to get it working, but later got it working with a script tag
I think I figured out what the problem was. I am using docker. Are you as well? Or a similar cm solution?
Node couldn't access the url from inside the container
@Sinnbeck I am not, my stack is installed directly in my computer. Running MAMP for Mac, which means PHP, Apache, Node, everything runs in the same environment as puppeteer. I really don't understand why it doesn't work without feeding the StyleTag directly through options :S ... super weird.
@undeportedmexican yeah that is indeed strange. Can you resolve the url from php?
@Sinnbeck I did not think about testing this. I just did it like this:
$data = Http::get('https://delsan.local.test/app/css')
and I got a "certificate problem: unable to get local issuer certificate" error. Makes sense to think this could be the problem. I know I can resolve the address in my browser.
@Sinnbeck Yes, I used ->ignoreHttpsErrors() and even paired it with ->waitUntilNetworkIdle().
Still the only thing that worked was including ->setOption('addStyleTag', json_encode(['path' => 'css/app.css']))
Edit:
I feel like I'm missing knowledge on how Puppeteer works, and there may be some logic onto why it's not working directly.
@undeportedmexican yeah me too. I started writing a manual script to debug back when I had issues, but gave up when I got it working
@Sinnbeck Yeah, it's the kind of thing that's super frustrating, as there are no pointers as to what to fix. In the end, it's working for me too, so that's that. I appreciate the time you took on this man.
@undeportedmexican one idea. Is it possible to run the project with http on localhost? Maybe it cannot resolve the domain. That was the problem with my docker setup
@Sinnbeck Man ... this is incredibly annoying. It's working properly now, and I can't seem to be able to break it for testing purposes. It just started working. Thought it might've been something around cache, but not sure if puppeteer caches anything.
It's working now and I cannot reproduce the error that I've been battling the entire weekend (Insert clown face here)
@undeportedmexican know that feeling all too well. Maybe there was some weird cert issue that it could not overcome and it was just reissued
@Sinnbeck Absolutely infuriating jajaja I've spent the past 30 minutes trying to break the functionality of my app (and failing at it). But now I'll refuse to let this bug eat up more of my time. I'll just celebrate the win and move on.
@undeportedmexican yeah. Just put a mental note that you fixed it by being awesome or something like that, and it shouldn't bother you as much
@Sinnbeck I love this philosophy jajaja will adopt it for sure.
@Sinnbeck Sorry, I know this is an old post but I think I am running into this issue myself. I am using sail (docker) and cannot get css or image files to show when the PDF is generated, although they work fine when rendered as a view. I am sure it must be the same issue of Node not being able to access 'localhost' inside the container. I was hoping you might remember what you did to fix it?
Please or to participate in this conversation.