Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playwright Chromium Doesn't Load Fonts in Production

Tags:

playwright

I'm using Chromium from Playwright to Convert Html to PDF Buffer without saving the file somewhere, I'm using Next API to do this, so the issue is that locally all my Google Font Links are loaded and the document is beeing displayed correctly and converted, the issue is when i deploy the codebase to DigitalOcean (using App feature and Dockerfile) then the fonts are not loaded, so the resposne and everything gets returned but the Buffer when converted to a document doesn't contain the fonts.

This is the main function (of the route, exluding not needed logic):

import { chromium } from "playwright"

const HtmlToPdf = async (req, res) => {
    try {
        let { dynamicHtml } = req.body;

        const browser = await chromium.launch({ 
            headless: true,
            args: ['--font-render-hinting=none', '--disable-web-security'],
        });

        const context = await browser.newContext();
        const page = await context.newPage();

        await page.setContent(dynamicHtml);
        await page.emulateMedia({media: "screen"});
        await page.evaluate (() => document.fonts.ready);

        const pdfBuffer = await page.pdf({ format: "A4", printBackground: true });

        await browser.close();

        if (!pdfBuffer) // return error and end the request

        // else here return the buffer and end the request
    } 
    
    catch (error) {
         // return error and end the request
    }
}

export default HtmlToPdf;

I tried passing some arguments I could find, in case the font needs time to load, but that didn't work either, I also added my docker file in case someone might need it to understand more:

# Use Node 18 Base Image
FROM node:18 

# Update and upgrade apt-get
RUN apt-get update && apt-get upgrade -y

# Install Chromium
RUN apt-get install -y chromium 

# Set working directory
WORKDIR ./ 

# Copy all files from current directory to working directory
COPY . . 

# Install dependencies
RUN npm ci 


# Build Microservices
RUN npm run build

# Expose port 2000
EXPOSE 2000 

# Set Chromium binary path
ENV CHROME_BIN=/usr/bin/chromium-browser

# Skip Chromium download
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

# Set Puppeteer arguments
ENV PUPPETEER_ARGS='--no-sandbox'

# Start Microservices
CMD [ "npm", "start" ]

I'm not sharing any file regarding the html, because that works perfectly fine locally and as A Html export.

I used args flags and font waiting from chromium playwright but nothing from those.

like image 609
bfzli Avatar asked Oct 25 '25 07:10

bfzli


1 Answers

Have a go at dropping this script tag in the head element. Kind of hacky but it worked for me! I also set font-display: swap; as a backup.

<script>
    document.addEventListener('DOMContentLoaded', async () => {
        await document.fonts.ready;
    });
</script>

Update: I should mention I had to use page.GoToAsync(myUrl) instead of page.SetContent(htmlContent) to get my fonts to render at all. Unfortunately wasn't able to figure it out with the SetContent method.

like image 134
highlife Avatar answered Oct 28 '25 05:10

highlife



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!