在Nest.js中用Puppeteer渲染EJS模板实现本地热重载可行吗?
解决Nest.js中Puppeteer+EJS的模板渲染与PDF生成问题
问题1:无法加载本地EJS模板文件
你的代码中直接使用file.buffer但未定义file变量,也没有正确读取本地EJS文件。需要通过文件系统模块定位并读取模板内容:
解决方案
- 导入
fs和path模块,处理文件路径与读取操作 - 使用
path.resolve拼接模板文件的绝对路径,避免相对路径定位错误 - 用
fs.readFileSync读取EJS文件的文本内容
问题2:Puppeteer的Buffer获取错误
const buffer: Buffer = await page;这行代码逻辑错误,page是Puppeteer的Page实例,不能直接转为Buffer。要生成PDF格式的Buffer,需要调用page.pdf()方法。
解决方案
替换错误代码为const buffer: Buffer = await page.pdf();,可按需配置PDF参数(如纸张格式、边距、背景渲染等)
修改后的完整服务代码
import { Injectable } from '@nestjs/common'; import * as fs from 'fs'; import * as path from 'path'; import * as data from './json/index.json'; import * as ejs from 'ejs'; import puppeteer, { Browser, Page } from 'puppeteer'; @Injectable() export class RenderPayloadToBrowserService { async renderPayload(): Promise<Buffer> { try { // 定位并读取EJS模板文件(替换为你的实际文件路径) const templatePath = path.resolve(__dirname, './templates/index.ejs'); const templateContent = fs.readFileSync(templatePath, 'utf-8'); // 渲染EJS模板,传入JSON数据 const content: string = ejs.render(templateContent, { data }); // 启动Puppeteer浏览器 const browser: Browser = await puppeteer.launch({ headless: 'new', // 使用新版无头模式 ignoreDefaultArgs: ['--disable-extensions'], args: ['--no-sandbox'] }); const page: Page = await browser.newPage(); // 等待页面资源加载完成后再生成PDF await page.setContent(content, { waitUntil: 'networkidle0' }); // 生成PDF Buffer const buffer: Buffer = await page.pdf({ format: 'A4', printBackground: true, margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' } }); await browser.close(); return buffer; } catch (error) { console.error('渲染或PDF生成失败:', error); throw error; } } // 新增方法:返回渲染后的HTML用于浏览器预览(支持热重载) async renderHtml(): Promise<string> { const templatePath = path.resolve(__dirname, './templates/index.ejs'); const templateContent = fs.readFileSync(templatePath, 'utf-8'); return ejs.render(templateContent, { data }); } }
实现EJS编辑热重载
- 配置Nest热重载:修改
nest-cli.json,开启静态文件监听:
{ "compilerOptions": { "watchAssets": true, "assets": ["**/*.ejs"] } }
- 新增预览路由:在控制器中添加路由返回渲染后的HTML,浏览器访问时修改EJS文件后刷新即可看到更新:
import { Controller, Get, Res } from '@nestjs/common'; import { Response } from 'express'; import { RenderPayloadToBrowserService } from './render-payload-to-browser.service'; @Controller() export class AppController { constructor(private readonly renderService: RenderPayloadToBrowserService) {} // PDF生成路由(原Postman调用路由) @Get('generatePdf') async generatePdf(@Res() res: Response) { const buffer = await this.renderService.renderPayload(); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', 'attachment; filename="template.pdf"'); res.send(buffer); } // 模板预览路由(支持热重载) @Get('renderTemplate') async renderTemplate(@Res() res: Response) { const html = await this.renderService.renderHtml(); res.setHeader('Content-Type', 'text/html'); res.send(html); } }
- 启动热重载模式:使用
nest start --watch命令启动应用,修改EJS文件后,Nest会自动重新编译,刷新浏览器的localhost:8016/renderTemplate即可看到最新模板效果。
内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz
相关产品推荐
相关产品推荐

