简体   繁体   中英

Using Puppeteer to screenshot an EJS template with NodeJS and Express

I have NodeJs/Express app in which I would like to open new browser window and render local EJS view into it. I am trying to do it using Puppeteer.

const puppeteer = require('puppeteer');
router.post('/new_window', async (req, res) => {
  try {
     const browser = await puppeteer.launch({headless: false});
     const page = await browser.newPage();
     const pageContent = ejs.render('../views/mypage.ejs', {})  
     await page.setContent(pageContent)
     //await page.screenshot({path: 'example.png'});
     // await browser.close();
  } catch (err) {
     res.status(500)
     console.log(err)
     res.send(err.message)
  }
})

In the browser instead of page layout I get:

../views/mypage.ejs

Instead of:

await page.goto(...); // This code is acting like your browser's address bar

Try

const pageContent = ejs.render('../views/mypage.ejs', {data to populate your .ejs page}) //This is sudo code. Check ejs docs on how to do this 
await page.setContent(pageContent)

The code above will let you create your page on your server. With page.setContent(..) you can load any string of HTML.

OP made an edit that correctly uses page.setContent rather than page.goto , however, there's still an issue. ejs.render() is used to run EJS on a template in string form, so it's treating the file path as the template itself. If you want to read the file into a string first (possibly when your app starts, if the template never changes), ejs.render() will work.

The other approach is to use the EJS method that accepts a path, ejs.renderFile() . Here's a minimal example showing the usage:

const ejs = require("ejs"); // 3.1.8
const express = require("express"); // ^4.18.1
const puppeteer = require("puppeteer"); // ^19.1.0

express()
.get("/greet", (req, res) => {
  let browser;
  (async () => {
    browser = await puppeteer.launch();
    const [page] = await browser.pages();
    const html = await ejs.renderFile("greet.ejs", {name: "world"});
    await page.setContent(html);
    const buf = await page.screenshot();
    res.contentType("image/png");
    res.send(buf);
  })()
    .catch(err => {
      console.error(err);
      res.sendStatus(500);
    }) 
    .finally(() => browser?.close());
})
.listen(3000);

Where greet.ejs contains:

<!DOCTYPE html>
<html>
<body>
<h1>Hello, <%- name %></h1>
</body>
</html>

To make a PDF with Express, EJS and Puppeteer, see Express/Puppeteer: generate PDF from EJS template and send as response .

To reuse the browser across routes, see this answer for a possible approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM