简体   繁体   English

使用 Puppeteer 使用 NodeJS 和 Express 截取 EJS 模板

[英]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.我有 NodeJs/Express 应用程序,我想在其中打开新的浏览器 window 并在其中呈现本地 EJS 视图。 I am trying to do it using Puppeteer.我正在尝试使用 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.使用page.setContent(..)您可以加载任何 HTML 字符串。

OP made an edit that correctly uses page.setContent rather than page.goto , however, there's still an issue. OP 进行了正确使用page.setContent而不是page.goto的编辑,但是,仍然存在问题。 ejs.render() is used to run EJS on a template in string form, so it's treating the file path as the template itself. ejs.render()用于在字符串形式的模板上运行 EJS,因此它将文件路径视为模板本身。 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.如果您想首先将文件读入字符串(可能在您的应用程序启动时,如果模板从未更改), ejs.render()将起作用。

The other approach is to use the EJS method that accepts a path, ejs.renderFile() .另一种方法是使用接受路径的 EJS 方法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:其中greet.ejs包含:

<!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 .要使用 Express、EJS 和 Puppeteer 制作 PDF,请参阅Express/Puppeteer:从 EJS 模板生成 PDF 并作为响应发送

To reuse the browser across routes, see this answer for a possible approach.要跨路由重用浏览器,请参阅此答案以了解可能的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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