导航菜单

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 idle
  • waitForSelector('#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 size
  • printBackground: true: Print background colors
  • margin: 20mm margins

Run PDF Generation

Execute the following command to generate PDF:

pnpm pdf

The script will automatically:

  1. Start Vite dev server
  2. Open page in headless browser
  3. Render page and generate PDF
  4. Close browser and server
  5. 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 chrome

Next Step

Now we have completed the PDF generation feature, next we will learn how to customize resume styles in the Custom Styles chapter.

搜索