PDF Generation
This chapter will guide you through using Puppeteer to export the resume page to a high-quality A4 PDF.
Puppeteer Introduction
Puppeteer is a Node.js library that provides a high-level API to control Chrome or Chromium browsers. We can use it to:
- Render pages in a headless browser
- Capture page screenshots
- Generate PDFs
Create PDF Generation Script
Create scripts/generate-pdf.ts:
import puppeteer from 'puppeteer'
import { createServer } from 'vite'
import { resolve } from 'path'
async function generatePDF() {
console.log('Starting PDF generation...')
const vite = await createServer({
configFile: resolve('./vite.config.ts'),
})
await vite.listen()
const port = vite.config.server?.port || 5173
const url = `http://localhost:${port}`
console.log(`Vite server running at ${url}`)
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
})
try {
const page = await browser.newPage()
await page.setViewport({
width: 643,
height: 971,
deviceScaleFactor: 2
})
await page.goto(url, {
waitUntil: 'networkidle0',
timeout: 30000
})
await page.waitForSelector('#app')
await new Promise(resolve => setTimeout(resolve, 1000))
await page.pdf({
path: 'temp/output.pdf',
format: 'A4',
printBackground: true,
margin: {
top: '20mm',
right: '20mm',
bottom: '20mm',
left: '20mm'
}
})
console.log('PDF generated successfully: temp/output.pdf')
} catch (error) {
console.error('Error generating PDF:', error)
throw error
} finally {
await browser.close()
await vite.close()
}
}
generatePDF().catch(console.error)Script Explanation
1. Start Vite Dev Server
const vite = await createServer({
configFile: resolve('./vite.config.ts'),
})
await vite.listen()We dynamically start the Vite dev server, so we don’t need to manually run pnpm dev.
2. Set Viewport Size
await page.setViewport({
width: 643,
height: 971,
deviceScaleFactor: 2
})width: 643: A4 content area width (170mm ≈ 643px @ 96 DPI)height: 971: A4 content area height (257mm ≈ 971px @ 96 DPI)deviceScaleFactor: 2: Higher clarity, suitable for printing
3. Wait for Page Render
await page.goto(url, {
waitUntil: 'networkidle0',
timeout: 30000
})
await page.waitForSelector('#app')
await new Promise(resolve => setTimeout(resolve, 1000))networkidle0: Wait for network to be completely idlewaitForSelector('#app'): Wait for Vue app to mount- Extra 1 second wait to ensure all content is rendered
4. Generate PDF
await page.pdf({
path: 'temp/output.pdf',
format: 'A4',
printBackground: true,
margin: {
top: '20mm',
right: '20mm',
bottom: '20mm',
left: '20mm'
}
})format: 'A4': A4 paper sizeprintBackground: true: Print background colorsmargin: 20mm margins
Run PDF Generation
Execute the following command to generate PDF:
pnpm pdfThe script will automatically:
- Start Vite dev server
- Open page in headless browser
- Render page and generate PDF
- Close browser and server
- Output PDF to
temp/output.pdf
Common Issues
1. Incomplete PDF Content
If PDF content is incomplete, you can increase wait time:
await new Promise(resolve => setTimeout(resolve, 2000))2. Font or Style Issues
Make sure to use @media print rules in CSS:
@media print {
body {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}3. Timeout Error
If page loading times out, you can increase timeout:
await page.goto(url, {
waitUntil: 'networkidle0',
timeout: 60000
})4. Puppeteer Can’t Find Browser
Make sure Chromium is installed:
npx puppeteer browsers install chromeNext Step
Now we have completed the PDF generation feature, next we will learn how to customize resume styles in the Custom Styles chapter.
