从零开始:使用 Node.js 构建自动化海报生成服务
1. 项目背景
在开发小程序时,我们需要分享动态生成不同内容的海报,实时生成带有文字标注的海报。为了追求高质量、可维护性和高效率,我们放弃了传统的 Canvas 方案,选用了更为现代化的Satori + Resvg + Sharp架构。
2. 技术选型对比
为什么选择这套组合,而不是node-canvas?
| 特性 | Satori 架构 | Canvas 方案 |
| 开发方式 | JSX/CSS (Flexbox) | 命令式 API (填充坐标) |
| 自动布局 | 支持,自动处理换行/对齐 | 需手动计算换行算法 |
| 可维护性 | 高,修改样式简单 | 低,改动布局需重算坐标 |
3. 核心实现方案
服务整体链路分为三个步骤:
Satori: 将 HTML/CSS 结构转换为 SVG 矢量图。
Resvg: 将 SVG 渲染为 PNG 图片 buffer。
Sharp: 将图片层合成到背景模板上。
关键代码逻辑 (posterGenerator.js)
JavaScript
const svg = await satori({ type: 'div', props: { style: { display: 'flex', position: 'relative', width: 750, height: 1000 }, children: [ { type: 'div', props: { style: { position: 'absolute', top: 388, left: 245, fontSize: 32, color: 'white' }, children: `¥${price}/人` } } ] } }, { width: 750, height: 1000, fonts: [...] });4. 生产环境避坑指南
在开发过程中,我们遇到了几个核心挑战,总结如下:
“方块”乱码问题:根源在于字体文件缺失货币符号(¥)。解决方案:下载完整版的“思源黑体 (Noto Sans SC)”而非精简版或 Variable 字体。
Satori 布局报错:必须显式声明
display: flex。尺寸不匹配:
Sharp.composite报错是因为图层尺寸超出背景,需确保 Satori 的width/height与背景图像素精确对齐。
5. 相关工具网站
免费字体网站: 阿里巴巴普惠体
在线ps工具网站:Photopea | Online Photo Editor