使用 Node.js 20+ 在 AWS Lambda 上运行 Puppeteer/Chromium 的操作指南
上次我使用Puppeteer生成PDF时,一切运行良好,当时我们使用的是AWS Linux 2和Node.js 18。但是当我们切换到AWS Linux 2023并升级Node.js版本到20.x之后,开始遇到各种问题。我们解决了这些问题后,最终成功生成了PDF,但生成的PDF却损坏了。
经过与团队的讨论,我们决定将Puppeteer迁移到AWS Lambda,这样无论我们在实例中做出何种更改,都不会影响到PDF的生成功能。这也有助于我们降低成本,因为生成相关的PDF报告是管理员日常执行的任务。我们按照以下步骤成功地将Puppeteer迁移至了AWS Lambda。
1 准备 Lambda 代码:创建一个任意名字的文件夹;在我的情况中,我需要创建一个叫 puppeteer-lambda
的文件夹。之后,通过以下命令初始化 npm 包。
在终端中输入以下命令来初始化 npm 项目,并自动填写 package.json
文件:
npm init --y
注释:--y
参数会自动确认所有默认设置,无需手动输入确认。
请安装以下包并确保安装的是指定的版本,可以使用下面的命令。
yarn add @sparticuz/chromium@122.0.0 puppeteer-core@22.5.0
安装完包并进行了一些编辑之后,我的“package.json
”如下:
{
"名称": "puppeteer-lambda",
"版本": "1.0.0",
"主文件": "index.mjs",
"脚本": {
"测试": "echo \"错误:未指定测试\" && exit 1"
},
"关键字": [],
"作者": "",
"许可证": "ISC",
"描述": "",
"依赖": {
"@sparticuz/chromium": "122.0.0",
"puppeteer-core": "22.5.0"
}
}
现在新建一个叫index.mjs
的文件,然后把下面这段代码复制进去:
import chromium from "@sparticuz/chromium";
import puppeteer from "puppeteer-core";
export const handler = async (event, _context, _callback) => {
let browser = null;
let result = null;
// await chromium.font("/var/task/fonts/NotoColorEmoji.ttf");
// 要使用 URL,建议如下代码
// await chromium.font(
// "https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"
// );
try {
// 从事件对象中提取 HTML
const html = event.body.html;
const args = [...chromium.args, "--disable-gpu-sandbox"];
// 创建 puppeteer 浏览器实例
browser = await puppeteer.launch({
args: args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
ignoreHTTPSErrors: true,
dumpio: true,
});
// 创建一个新的页面
const page = await browser.newPage();
// 将 HTML 内容设置为
await page.setContent(html, { waitUntil: "domcontentloaded" });
// 将媒体类型设置为屏幕
await page.emulateMediaType("screen");
// 若使用自定义字体
await page.evaluateHandle("document.fonts.ready");
// 配置生成 PDF
const pdf = await page.pdf({
// path: "result.pdf",
margin: { top: "100px", right: "50px", bottom: "100px", left: "50px" },
printBackground: true,
format: "A4",
});
// 将 PDF 转为 base64 格式
result = pdf.toString("base64");
} catch (error) {
console.log("-----handler---", error);
} finally {
if (browser !== null) {
await browser.close();
}
}
return result;
};
你的文件夹结构可以像下面这样:
.
└── puppeteer-lambda/
├── fonts/ (仅当你想要上传字体文件时)/
│ └── NotoNaskhArabic-VariableFont_wght.ttf (任何字体文件,如)
├── node_modules
├── index.mjs
├── package.json
└── yarn.lock (取决于你使用的包管理器)
现在打开文件夹并把文件夹里的所有文件压缩:_(注意:nodemodules也会被压缩在一起)
压缩文件(Mac)— 在Windows上操作步骤相同
2号) 在 AWS Lambda 上部署代码访问https://console.aws.amazon.com/并登录您的账户。在搜索栏中输入Lambda,然后点击搜索结果。接下来,点击创建函数按钮。
Searching for Lambda in AWS Console
现在在创建面板中配置您的Lambda函数。我把它命名为puppeteer-lambd
;您可以根据喜好为其命名。如果有需要的话,可以开启函数URL。Lambda函数创建的过程如下:
Lambda Creation Screen Section 1
Lambda Creation Screen Section 2
创建 Lambda 之后,你会看到如下屏幕;点击配置来更新配置。
After Lambda Creation Screen
现在,你可以相应地更新内存(RAM)、临时存储空间和超时。
Lambda Configuration Pane
你可以通过两种方式上传压缩文件:如果压缩文件小于50MB的话,你可以直接上传。否则,你需要先将文件上传到S3,再复制其URL到输入框里。
Uploading Compressed File
现在你可以去测试选项卡里测试一下你的代码
Testing the Lambda Function
现在,你可以在“版本”选项卡中点击按钮来发布新版本出来。
Publishing a New Version
3) 在后端添加代码:你现在可以在后端代码中添加,并在路由中调用这个工具函数来获取PDF文件。
// index.js
const AWS = require("aws-sdk");
AWS.config.loadFromPath(`./aws.config.json`);
exports.generatePdfFile = async ({ html }) => {
try {
const lambda = new AWS.Lambda({});
// 调用 Lambda 函数
const lambdaResult = await lambda
.invoke({
FunctionName: "puppeteer-lambd",
Payload: JSON.stringify({
body: {
html: html,
},
}),
})
.promise();
if (lambdaResult.StatusCode === 200) {
// 响应体中包含的是 base64 编码的 PDF 内容
const pdfBase64 = JSON.parse(lambdaResult.Payload);
// 将 base64 字符串解码为缓冲区(二进制数据)
const pdfBuffer = Buffer.from(pdfBase64, "base64");
// 将 PDF 缓冲区返回给客户端
return pdfBuffer;
} else {
console.log(lambdaResult.Payload);
throw new Error("生成 PDF 发生错误");
}
} catch (error) {
console.error("调用 Lambda 函数失败:", error);
throw new Error("生成 PDF 发生错误");
}
};
添加一个用于 AWS 账户信息的配置文件以...
{
"accessKeyId": "<your-access-key>", // 访问密钥ID
"secretAccessKey": "<your-secret-access-key>", // 密钥访问密钥
"region": "<your-region>" // 地区
}
就这样,祝你编程开心!😊
访问代码:
GitHub - faraasat/running-puppeteer-on-aws-lambda: 文章示例代码示例 - 在 AWS Lambda 上运行 Puppeteer/Chromium 的示例 - 使用 Node.js 20+ - 指南…github.com如果你喜欢我讲的故事,可以关注我一下,在Farasat Ali — Medium可以找到更多有趣的的小贴士。
另外,查看我的个人作品集作品集,网址是:
看看 Farasat 如何实现业务的惊人增长 | 轻松获得最佳效果,更令人惊讶的是,你还可以…认识 Farasat Ali,一位专注于尖端编程和网络技术的软件工程师及计算机科学爱好者…www.farasat.me查看其他相关文章:
使用 Worker Threads 和 Clusters 扩大 Node.js/Express 应用规模 —— 使用 Worker Threads 和 Clusters 扩展 Node.js/Express 应用简易指南Node.js 是一个流行的基于 Google V8 引擎的 JavaScript 运行环境,它以非阻塞特性著称…blog.stackademic.com 使用React Fiber Offscreen减少阻塞时间以优化Next.js中的3D模型渲染每次我们在Web上执行CPU密集型操作时,页面会变得卡顿且一段时间内无法响应。渲染一个…blog.stackademic.com 用Ready Player、Mixamo和Next.js给你的作品集网站添上活力四射的动画 在当今竞争激烈的世界里,作品集网站不仅仅是漂亮的图片和代码片段的堆砌… 如何优化您的Next.js应用:通过卸载计算密集型任务从主线程到Web WorkersJavaScript,作为我们浏览器上运行的语言,本质上运行在单一主线程上,我们可以将CPU密集型任务卸载到Web Workers上……blog.stackademic.com 在 Next.js 13+ App 目录中使用 @Serwist 启用 PWA — 简单教程Progressive Web App 允许在离线时访问已浏览的页面,推送通知并创建桌面图标。学习如何实现它……blog.stackademic.com [使用 Redux Toolkit 和 Redux State Sync 在 Next.js 13+ 中进行标签页间的状态同步 — 简单指南当你在 Next.js 中使用 Redux 时,通常需要同步不同标签页的状态。本文分享了一个简单的方法。
更多详情请访问...https://medium.com/syncing-tabs-in-next-js-13-using-redux-toolkit-redux-state-sync-simple-guide-f953329c6beb?source=post_page-----4ab26510e91b--------------------------------]
感谢您一直读到最后。在您离开前,
- 请考虑点赞并关注作者哦!👏
- 关注我们 推特 | LinkedIn | YouTube | Discord
- 我们还有其他平台等着您探索:In Plain English | CoFeed | Differ
- 想要了解更多内容,欢迎访问 Stackademic.com
共同学习,写下你的评论
评论加载中...
作者其他优质文章