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>
<!-- … -->
My guess is that Sail is doing something different when using Vite to compile the CSS file, specifically using a different path than Lando. What could that be?
Working with Tighten, a highly knowledgeable team of Laravel professionals, I finally have an answer.
I needed to set
PHP_CLI_SERVER_WORKERS=3in my.envfile because Sail runsphp artisan serveby 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.