I’m trying to run a Node.js/Express application that uses Puppeteer to generate PDFs on DigitalOcean App Platform. Despite installing Chromium through an .aptfile, I’m encountering issues with launching the browser.
Environment
Platform: DigitalOcean App Platform
Node.js version: 20.x
Puppeteer version: Latest
Deployment: Using .aptfile for dependencies
Code
Here’s my Express endpoint that uses Puppeteer:
import type { Request, Response } from "express";
import type { InvoiceRequest } from "./types/invoiceRequest";
import * as pug from "pug";
import puppeteer from "puppeteer";
import express from "express";
import fs from "fs";
const app = express();
const port = 3000;
// Precompile the Pug template once at startup
const compiledFunction = pug.compileFile("./templates/invoice.pug");
// Optional timeout middleware
app.use((req, res, next) => {
res.setTimeout(60000, () => {
res.status(504).json({ error: "Request timed out." });
});
next();
});
// Middleware to parse JSON bodies
app.use(express.json());
app.get("/", (req: Request, res: Response) => {
res.send("Hello World!");
});
app.post(
"/invoice/generate-invoice",
async (req: Request<{}, {}, InvoiceRequest>, res: Response) => {
console.log("Received request:", req.body);
try {
const invoiceData = req.body;
// Calculate totals
const subtotal = invoiceData.products.reduce(
(sum, product) => sum + product.price,
0
);
const vat = subtotal * 0.25; // 25% VAT
const total = subtotal + vat;
// Format dates
const invoiceDate = new Date().toISOString().split("T")[0];
const dueDate = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000)
.toISOString()
.split("T")[0];
// Generate HTML using Pug template
const html = compiledFunction({
});
// Use Puppeteer to generate the PDF from HTML
const browser = await puppeteer.launch({
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--single-process",
"--no-zygote",
],
executablePath: "/layers/digitalocean_apt/apt/usr/bin/chromium-bsu",
});
const page = await browser.newPage();
await page.setContent(html, { waitUntil: "networkidle0" });
const pdfBuffer = await page.pdf({ format: "A4" });
await browser.close();
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", "attachment; filename=invoice.pdf");
res.send(pdfBuffer);
// store the pdf localy
fs.writeFile("invoice.pdf", pdfBuffer, (err) => {
if (err) {
console.error("Error saving invoice:", err);
} else {
console.log("Invoice saved successfully");
}
});
} catch (error) {
console.error("Error generating invoice:", error);
res.status(500).json({ error: "Failed to generate invoice" });
}
}
);
app.listen(process.env.PORT || port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
This is my Aptfile:
chromium
chromium-common
chromium-sandbox
ca-certificates
fonts-liberation
libappindicator3-1
libasound2
libatk-bridge2.0-0
# ... [other dependencies] ...
This is the Error i am getting in digital ocean:
Error generating invoice: Error: Browser was not found at the configured executablePath (/layers/digitalocean_apt/apt/usr/bin/chromium-bsu)
at ChromeLauncher.launch (/workspace/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserLauncher.js:76:19)