我自己做了个用来搜书和拍照生成读书笔记的微信小程序「番茄鉴书」。之前为了生成书和书摘的分享图片,调研了一下。发现小程序端的 Canvas 倒是可以,但是实现起来比较繁琐,而且不够灵活,要只是出于「学习」的目的,倒是可以一试。puppeteer 方案呢,相对就比较简单灵活一些了,写好展示页面,用 puppeteer 操作 headless chrome 访问 url 生成截图就好了。这种方案也比较成熟,实现成本也还好,最大的问题其实是服务器资源。
我自己用的服务器是阿里云 1 核 2 G 的 ECS。部署了 2个 koa api server,用 PM2 做进程守护;一个 Mysql 实例用来做 state/pre 环境。因为 Nodejs 和 Mysql 资源消耗的低消门槛,这些加起来差不多已经占去了很多内存,puppetter 再一跑起来我就经常收到阿里云的监控警报。并发再多几个得话我这些服务估计全得受影响,好在用得人不多。但其实问题就在这儿,为了这么一个使用量不多的功能,需要常驻一个服务,但只要有少量并发,这台机器的配置根本没法支撑。
于是我把这个海报生成的服务单独抽出来,做成了一个生成分享图片的服务 - Foolstack,通过函数计算/独立服务器部署,按调用次数付费。
从我目前这种方案切过去也很方便。实际替换过程也确实很方便,只需要更改一下之前请求我自己那个 puppetter 服务的部分:
const { data } = await axios({
url: poster.domain,
method: 'POST',
data: {
url: `${app.domain}/${type}/${id}?uid=${uid}`,
option: {
width: 500,
height: 780,
}
},
headers: {
'content-type': 'application/json; charset=utf-8',
Authorization: `Bearer ${poster.token}`,
},
responseType: 'arraybuffer',
})
然后把生成的图片存储一份,之后请求的时候就不用调用这个服务进行生成了,即加快了响应速度,也降低了生成成本。
生成效果如下:
书
书摘
这种提供 url 的方式,整个图片的生成过程会稍慢一点儿,毕竟会有额外的网络请求时间。如果使用另外一种方式,直接把页面 html 代码传过去,生成速度会更快一些。
后面我会增加一些内置的海报图模板,不用自己去写截图用的展示页面,只需要把需要的数据传过去就可以。不仅海报图的生成速度快了,整个的接入过程也会更快。
新增一个模板
// preset recommendation const { data } = await axios({ url: 'https://api.foolstack.net/v1/poster', method: 'POST', data: { preset: { id: 'recommendation', data: { item: { cover: 'https://cover.png', title: 'Foolstack', content: 'Foolstack 提供内置模板,满足 99% 以上互联网服务所需的分享海报,适合中小团队和独立开发者,只需把关键信息传给 API,自动填充模板生成海报。', info: '推荐你购买', }, user: { avatar: 'https://avatar.png', nickname: '糖伴西红柿' }, brand: { name: 'Foolstack', qrcode: 'https://qrcode.png', slogan: '专业分享海报图生成服务' }, } } }, headers: { 'content-type': 'application/json; charset=utf-8', Authorization: 'Bearer <Your API token>', }, responseType: 'arraybuffer', })
生成效果如图
新增一个电商类模板
// preset ecommerce const { data } = await axios({ url: 'https://api.foolstack.net/v1/poster', method: 'POST', data: { preset: { id: 'ecommerce', data: { item: { cover: 'https://images', symbol: '¥', tag: '699.9', label: '原价 ¥1299.9', info: '已售 1000 件', title: 'Foolstack', content: 'Foolstack 提供内置模板,满足 99% 以上互联网服务所需的分享海报,适合中小团队和独立开发者,只需把关键信息传给 API,自动填充模板生成海报。', }, styles: { backgroundColor = '#fafafa', bannerBackgroundColor: '#f56818', bannerForeColor: '#FFFFFF', brandForeColor: '#999', titleColor: '#111', contentColor: '#888' }, brand: { name: 'Foolstack', qrcode: 'https://images', slogan: '专业分享海报图生成服务' }, } } }, headers: { 'content-type': 'application/json; charset=utf-8', Authorization: 'Bearer <Your API token>', }, responseType: 'arraybuffer', })
生成效果
现在已经支持使用内置模板,只需要提供所需数据,就可以更方便地生成海报图了。
调用方式
// preset const { data } = await axios({ url: 'https://api.foolstack.net/v1/poster', method: 'POST', data: { preset: { id: 'imageShare', data: { user: { avatar: 'https://image.png', nickname: '糖伴西红柿' }, cover: 'https://image.png', content: 'Foolstack 提供内置模板,满足 99% 以上互联网服务所需的分享海报,适合中小团队和独立开发者,只需把关键信息传给 API,自动填充模板生成海报。', brand: { name: 'Foolstack', qrcode: 'https://image.png', slogan: '专业分享海报图生成服务' }, } } }, headers: { 'content-type': 'application/json; charset=utf-8', Authorization: 'Bearer <Your API token>', }, responseType: 'arraybuffer', })
生成效果如下
其他方式可以参考 Foolstack 的 NodeJS 部分的代码示例。
更多模板还在陆续添加中…