Skip to content
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

DOMPDF does not work with Sail? #3379

Closed
chrispmcgee opened this issue Jan 16, 2024 · 5 comments
Closed

DOMPDF does not work with Sail? #3379

chrispmcgee opened this issue Jan 16, 2024 · 5 comments
Labels

Comments

@chrispmcgee
Copy link

I have a project using Laravel 10 and Lando for a local dev environment. We recently implemented Laravel DOMPDF to turn a Blade template into a PDF.

This has been working fine, so long as we run lando npm run build rather than lando npm run dev so that it builds the stylesheet file in the correct directory and Vite links to the correct file.

Now, I have implemented Laravel Sail, which also uses Vite, for our local dev environment as an alternative to Lando. It works perfectly except for Laravel DOMPDF. It seems unable to find the linked stylesheets and images, so the resulting PDF is unstyled and missing all the images.

Nothing has changed in the vite.config.js file, and the only thing I changed in .env is altering APP_URL=http://nexus.lndo.site/ to APP_URL=http://localhost/.

Here's the vite.config.js file:

/// <reference types="vitest" />
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader';
import path from 'path';

export default defineConfig({
    server: {
        https: false,
        host: true,
        port: 3009,
        hmr: {
            host: 'localhost',
            protocol: 'ws',
        },
    },
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
            script: {
                defineModel: true,
            },
        }),
        svgLoader()
    ],
    test: {
        globals: true,
        environment: 'happy-dom',
        setupFiles: ['./resources/js/tests/setup.js'],
        unstubGlobals: true,
    },
    resolve: {
        alias: {
            'ziggy-js': path.resolve('vendor/tightenco/ziggy/dist/vue.es.js'),
            // 'vendor/tightenco/ziggy/dist/vue.es.js' if using the Vue plugin
        },
    },
});

And here is a snippet of the dispatch-sheet.blade.php file that is used for the PDF rendering.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name', 'IEL Nexus') }}</title>

    <!-- Google fonts needed since Font Bunny doesn't work with dompdf -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Homemade+Apple&family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap" rel="stylesheet">

    @vite('resources/css/app.css')
    <style>
        body {
            font-size: 10px;
        }

        .font-sans {
            font-family: 'Roboto', sans-serif;
        }

        .font-signature {
            font-family: 'Homemade Apple', handwriting, cursive;
        }
        dt {
            float: left;
            font-weight: bold;
            clear: both;
            padding-top: 5px;
        }

        dd {
            padding-top: 5px;
            text-align: right;
        }

        .w-third {
            width: 33%;
        }

        .w-fifth {
            width: 20%;
        }

        .w-two-fifths {
            width: 40%;
        }

        .w-quarter {
            width: 25%;
        }

        .w-half {
            width: 50%;
        }

        td {
            padding-top: 5px;
        }
    </style>
</head>

<body class="font-sans">
    <table class="w-full border-separate table-fixed border-spacing-2">
        <tr>
            <td class="w-two-fifths pl-2 align-top">
                <img src="{{ asset('images/logo-ratecon.png') }}" alt="RateCon Logo">
            </td>
            <td class="w-two-fifths px-2 align-top">
                <p><strong>Dispatch Sheet</strong></p>
                <p>
                    Integrity Express Logistics<br>
                    PO Box 42275 - Cincinnati, OH 45242<br>
                    Tel.: 937-502-1024 Ext: 1024 - Fax: 855-600-2467 - Email: {{ $customer_email }}
                </p>
            </td>
            <td class="w-fifth pl-2 align-top text-right">
                <strong>IEL PO#: {{ $po_number }}</strong>
            </td>
        </tr>
    </table>
<!-- … -->

Here is a comparison of the outputs.

Lando:

FoxitPDFReader_6SCplxsSFL

Sail:

firefox_Biws06vGBr

My guess is that Sail is doing something different when using Vite to compile the CSS file, specifically using a path different from Lando's. What could that be?

@bsweeney
Copy link
Member

Happy to try to help but I use none of the cited frameworks, so 😬.

I guess my first question is, what is the actual URL of the stylesheet when using sail vs lando? Seems like if that's the main difference then maybe Dompdf is unable to access that URL (for reasons). Could be that localhost is blocked somehow? Or maybe it's redirected (latest release of Dompdf doesn't follow redirects).

You can try enabling additional debug logging for Dompdf itself. That may provide some information on why the stylesheet request is failing.

@chrispmcgee
Copy link
Author

Happy to try to help but I use none of the cited frameworks, so 😬.

I'm using Laravel DOMPDF, a wrapper for your package to make it easy to implement in a Laravel project. Laravel Sail is the current recommended way of setting up a Laravel local dev environment, at least if you're not using macOS, and it uses Docker containers to run all the PHP stuff. It uses Vite under the hood to build compiled versions of stylesheets and JavaScript files.

I guess my first question is, what is the actual URL of the stylesheet when using sail vs lando?

When I set show_warnings => true (thanks to a suggestion in this thread), you can see the URLs that DOMPDF is having trouble with:
DOMPDF errors

So the stylesheet's URL, for example, is http://localhost/build/assets/app-69148a16.css (Vite compiles all the stylesheets and minifies them into one .css file). What doesn't make sense is that I can copy/paste that exact URL into another browser window and see the stylesheet perfectly fine, so why can't DOMPDF? The same is true with the image at http://localhost/images/logo-ratecon.png.

Lando uses the same paths, the only difference is the domain, which is https://nexus.lndo.site/

Seems like if that's the main difference then maybe Dompdf is unable to access that URL (for reasons). Could be that localhost is blocked somehow? Or maybe it's redirected (latest release of Dompdf doesn't follow redirects).

As far as I can tell, localhost isn't blocked because I can access the stylesheet and image URLs directly without any problems. I also don't see them redirecting anywhere else.

You can try enabling additional debug logging for Dompdf itself. That may provide some information on why the stylesheet request is failing.

Perhaps it's because I'm using Laravel DOMPDF, but adding the code on that page under Configuration doesn't help. It gives me a bunch of PDF code (I think) that I cannot understand:

%PDF-1.7 1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 3 0 R >> endobj 2 0 obj << /Type /Outlines /Count 0 >> endobj 3 0 obj << /Type /Pages /Kids [6 0 R ] /Count 1 /Resources << /ProcSet 4 0 R /Font << /F1 8 0 R >> >> /MediaBox [0.000 0.000 612.000 792.000] >> endobj 4 0 obj [/PDF /Text ] endobj 5 0 obj << /Producer (��dompdf 2.0.4 + CPDF) /CreationDate (D:20240122145922+00'00') /ModDate (D:20240122145922+00'00') >> endobj 6 0 obj << /Type /Page /MediaBox [0.000 0.000 612.000 792.000] /Parent 3 0 R /Contents 7 0 R >> endobj 7 0 obj << /Length 72 >> stream 0.000 0.000 0.000 rg BT 34.016 734.579 Td /F1 12.0 Tf [(Dompdf)] TJ ET endstream endobj 8 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >> endobj xref 0 9 0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000274 00000 n 0000000303 00000 n 0000000452 00000 n 0000000555 00000 n 0000000677 00000 n trailer << /Size 9 /Root 1 0 R /Info 5 0 R /ID[] >> startxref 786 %%EOF 

@bsweeney
Copy link
Member

As far as I can tell, localhost isn't blocked because I can access the stylesheet and image URLs directly without any problems. I also don't see them redirecting anywhere else.

I'd say maybe remote resources aren't allowed, but then nexus.lndo.site also would not work. so presumably you are allowing remote resources somewhere (Pdf::setOption(['isRemoteEnabled' => true]);)

Block could be at the PHP level (thus your ability to access via browser but Dompdf failing). I don't think this is what's happening, but you can confirm by setting up a simple script within the application that just fetches the file:

echo file_get_contents("http://localhost/build/assets/app-69148a16.css");

Perhaps it's because I'm using Laravel DOMPDF, but adding the code on that page under Configuration doesn't help. It gives me a bunch of PDF code (I think) that I cannot understand.

Yes, that is the PDF source. Laravel seems to be giving you fairly details messaging so maybe this isn't necessary. Somebody with more experience with debugging Dompdf in Laravel would have to help us here.

@chrispmcgee
Copy link
Author

Working with Tighten, a highly knowledgeable team of Laravel professionals, I finally have an answer.

I needed to set PHP_CLI_SERVER_WORKERS=3 in my .env file because Sail runs php artisan serve by default, which means that only has a single process. Therefore, it cannot run the web request to render the HTML + the asset fetching from the PDF renderer simultaneously. So, setting this environment variable to a number higher than 1 tells the PHP built-in web server to spin up more workers, which solves this issue.

@bsweeney
Copy link
Member

That is not something I would have thought of. Thanks for providing your resolution.

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

No branches or pull requests

2 participants