Converting HTML to PDF is a common requirement in web applications. In this blog post, we'll explore how to create a Next.js API route that converts HTML to PDF using Puppeteer, and we'll ensure it works when deployed to Vercel.
While Puppeteer is a powerful tool for HTML to PDF conversion, it presents challenges when deploying to serverless environments like Vercel. The main issues are:
We'll use a combination of @sparticuz/chromium-min and puppeteer-core to overcome these limitations. Here's how we'll approach it:
First, create a new Next.js project or use an existing one. Then, install the necessary dependencies:
npm install @sparticuz/chromium-min puppeteer-core
To ensure compatibility and optimal performance, it's important to use the correct versions of the required packages. As of the latest testing, the following versions are recommended:
{ "dependencies": { "@sparticuz/chromium-min": "^129.0.0", "puppeteer-core": "^23.5.0" } }
Create a new file at app/api/html-to-pdf/route.js (for Next.js 13 app router) or pages/api/html-to-pdf.js (for Pages router). Here's the code:
const chromium = require("@sparticuz/chromium-min"); const puppeteer = require("puppeteer-core"); async function getBrowser() { return puppeteer.launch({ args: [...chromium.args, "--hide-scrollbars", "--disable-web-security"], defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath( `https://github.com/Sparticuz/chromium/releases/download/v129.0.0/chromium-v129.0.0-pack.tar` ), headless: chromium.headless, ignoreHTTPSErrors: true }); } export async function POST(request) { try { const { html } = await request.json(); const browser = await getBrowser(); const page = await browser.newPage(); await page.setContent(html, { waitUntil: "networkidle0" }); const pdfBuffer = await page.pdf({ format: "A4", printBackground: true, margin: { top: "1cm", right: "1cm", bottom: "1cm", left: "1cm" } }); await browser.close(); return new Response(pdfBuffer, { headers: { "Content-Type": "application/pdf", "Content-Disposition": 'attachment; filename="output.pdf"' } }); } catch (error) { console.error("Error generating PDF:", error); return new Response(JSON.stringify({ error: "Failed to generate PDF" }), { status: 500, headers: { "Content-Type": "application/json" } }); } }
Let's break down the key parts of this code:
The getBrowser function sets up Puppeteer with the minimal Chromium binary:
async function getBrowser() { return puppeteer.launch({ args: [...chromium.args, "--hide-scrollbars", "--disable-web-security"], defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath( `https://github.com/Sparticuz/chromium/releases/download/v129.0.0/chromium-v129.0.0-pack.tar` ), headless: chromium.headless, ignoreHTTPSErrors: true }); }
This configuration uses the @sparticuz/chromium-min package to provide a minimal Chromium binary compatible with serverless environments.
The main logic for PDF generation is in the POST function:
To use this API, send a POST request with the HTML content in the request body:
const response = await fetch('/api/html-to-pdf', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ html: '<h1>Hello, World!</h1>' }), }); if (response.ok) { const blob = await response.blob(); // Handle the PDF blob (e.g., download or display) }
When deploying to Vercel, keep these points in mind:
Execution Time: Vercel has a maximum execution time of 10 seconds for hobby plans and 60 seconds for pro plans. Optimize your HTML and PDF generation process to fit within these limits.
Memory Usage: Be mindful of memory usage. The minimal Chromium binary helps, but complex PDFs might still use significant memory.
Cold Starts: Serverless functions can experience cold starts. The first invocation might be slower as it needs to download and set up the Chromium binary.
Error Handling: Implement robust error handling to manage timeouts or resource constraints.
Caching: Consider implementing caching strategies for frequently generated PDFs to reduce load on your serverless functions.
This approach allows you to create a powerful HTML to PDF conversion API using Next.js and Puppeteer, compatible with Vercel's serverless environment. By leveraging @sparticuz/chromium-min and puppeteer-core, we overcome the main challenges of running Puppeteer in a serverless context.
The above is the detailed content of Creating a Next.js API to Convert HTML to PDF with Puppeteer (Vercel-Compatible). For more information, please follow other related articles on the PHP Chinese website!