关于javascript:用-Puppeteer-Nodejs-构建高效海报-截图生成服务

前言:在前端日常开发中,toC的业务难免会有一些截图或者生成海报的业务需要受限于html2canvas的不兼容性,或者canvas画图的款式局限性,目前咱们又有了一种新的解决方案,node + puppeteer的组合,

puppeteer

puppeteer 初识

Puppeteer 是 Google Chrome 团队官网的无界面(Headless)Chrome 工具。Chrome 作为浏览器市场的领头羊,Chrome Headless 将成为 web 利用 自动化测试 的行业标杆

那么咱们能够用puppeteer来些什么?

  • 生成页面的截图或者PDF
  • 主动模仿用户行为,表单提交、按钮点击等
  • 创立自动化测试环境
  • 捕捉站点的工夫线跟踪,以帮忙诊断性能问题。
  • 爬取 SPA 页面并进行预渲染(即’SSR’)

可见第一种个性正式咱们用的到的

puppeteer 装置

npm install puppeteer
// 下载内核步骤可能会失败,cnpm 或迷信上网

puppeteer 次要api

只介绍截图相干,如果须要其余个性的查问,请移步:https://github.com/puppeteer/…

1.启动实例

import * as puppeteer from 'puppeteer'

(async () => {
  await puppeteer.launch()
})()

2.网页截图

png截图

await page.setViewport({width, height})
  await page.goto(url)
  //对整个页面截图
  await page.screenshot({
      path: path.resolve(`./screenshot/${fileName}.png`),  //图片保留门路
      type: 'png',
      fullPage: false //边滚动边截图
  })

不仅如此 还能够模拟手机的device环境

import * as puppeteer from "puppeteer";
import * as devices from "puppeteer/DeviceDescriptors";
const iPhone = devices["iPhone 6"];

(async () => {
  const browser = await puppeteer.launch({
    headless: false
  });
  const page = await browser.newPage();
  await page.emulate(iPhone);
  await page.goto("https://baidu.com/");
  await browser.close();
})();

pdf截图

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto("https://example.com/");
  await page.pdf({
    displayHeaderFooter: true,
    path: 'example.pdf',
    format: 'A4',
    headerTemplate: '<b style="font-size: 30px">Hello world<b/>',
    footerTemplate: '<b style="font-size: 30px">Some text</b>',
    margin: {
      top: "100px",
      bottom: "200px",
      right: "30px",
      left: "30px",
    }
  });
  await browser.close();
})()

好~有了这些咱们就能够满足咱们根本截图需要了

根本架构

阐明

截图申请接口:此api会间接申请到 node 服务,会携带参数包含:

  • 托管页地址 (为要截取网页的地址)
  • 要截图的宽高
  • 截图的类型 (png/pdf)

截图托管页:动态的html页面。可url传参数去控制变量

node服务收到接口申请后,会申请托管页,构建一个要截取的网页,执行截图操作的api,返回截图buffer数据给申请的接口,到此为止,咱们基础架构就整顿结束了

上 demo 代码

前置环境,假如咱们当初曾经有一个可用的node环境(node + koa2)

// router层
const screenshotControllers = require('../controllers/puppeteer')

const router = new KoaRouter()
exports.router = router.post('/api/puppeteer/v1/screenshot', screenshotControllers.api.screenshot)
// conteoller层
const service = require('../service/puppeteer')

const screenshot = (ctx, next) => {
    return service.api.screenshot(ctx);
}

exports.api = {
    screenshot
}
// service层
const { getScreenshot } = require('../puppeteer/index')
exports.api = {
    screenshot: async (ctx) => {
        const { width, height, url, tid} = ctx.request.body
        const res = await getScreenshot(url, width, height, tid)
        console.log(res)
        if (res) {
            ctx.body = {
                code: 200,
                message: '胜利',
                data: res
            }
        }
    }
}
//具体业务层
const puppeteer = require('puppeteer');
const path = require('path')

exports.getScreenshot = async (url, width = 800, height = 600, fileName) => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  //设置可视区域大小,默认的页面大小为800x600分辨率
  await page.setViewport({width, height})
  await page.goto(url)
  //对整个页面截图
  await page.screenshot({
      path: path.resolve(`./screenshot/${fileName}.png`),  //图片保留门路
      type: 'png',
      fullPage: false //边滚动边截图
  })
  
  //执行cos 或 oss 脚本,把图片上传到cdn环境,此处因为调试,临时省略

  await page.close()
  await browser.close()

  return `${fileName}.png`
}

测试服务可用性

启动 node 服务

启动 psotman 模仿申请接口

1.百度


查看后果

2.掘金

{
    "url": "https://juejin.cn/",
    "width": 720,
    "height": 1080,
    "tid": 0
}

嗯,看起来也没啥问题

具体业务利用

目前有生成海报的需要,那么咱们应该怎么搞?

1.依据UI图,搞定托管页
2.依据传入的变量id,写好后端逻辑,

3.调用node服务,取得图片buffer 或图片cdn地址

await axios({
       method: 'POST',
       url: 'http://xxx/api/puppeteer/v1/screenshot',
       data: {
        url: `http://xxx/postFrame/home?lecCode=lec${i}`,
        width: 335,
        height: 525,
        tid: `lec${i}`
    }
   })

至此就大功搞成了,这种解决方案能够磨平各种运行环境的差异性,缩小本地生成图片的失败率

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理