Foreword: In daily front-end development, toC business will inevitably have some screenshots or poster generating business requirements are limited by html2Canvas incompatibility or canvas drawing style limitations. Now we have a new solution, the combination of Node and Puppeteer.
puppeteer
Puppeteer met
Puppeteer is Google Chrome’s official Headless Chrome tool. As the browser market leader, Chrome Headless will become an industry benchmark for automated testing of Web applications
So what can we use puppeteer for?
- Generate a screenshot or PDF of the page
- Automatic simulation of user behavior, form submission, button clicking, etc
- Create an automated test environment
- Capture a timeline trace of the site to help diagnose performance problems.
- Crawl SPA page and pre-render (i.e. ‘SSR’)
So the first feature is the one we use
Puppeteer installation
NPM install puppeteer // The download step may fail, CNPM or science onlineCopy the code
Main apis puppeteer
This section only describes screenshots. To query information about other features, go to github.com/puppeteer/p…
1. Start the instance
import * as puppeteer from 'puppeteer'
(async () => {
await puppeteer.launch()
})()
Copy the code
2. Screenshot of web page
PNG screenshots
SetViewport ({width, height}) await page.goto(url) // In the whole page screenshot await page.screenshot({path: Resolve ('./screenshot/${fileName}.png '), // Screenshot save path type: 'PNG ', fullPage: false})Copy the code
Not only that, it can also simulate the device environment of mobile phones
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(); }) ();Copy the code
PDF screenshots
(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(); }) ()Copy the code
Ok, so with this we can meet our basic screenshot needs
Basic architecture
instructions
Request interface: This API will directly request to the Node service, carrying parameters including:
- Hosted page address (for the address of the page to be captured)
- Want the width and height of the screenshot
- Type of screenshot (PNG/PDF)
Screenshot hosting page: Static HTML page. Url can pass parameters to control variables
After receiving the interface request, the Node service will request to host the page, build an API to capture the page, perform the screenshot operation, and return the screenshot buffer data to the requested interface. At this end, our infrastructure is organized
In the demo code
Front-end environment, assuming we now have a node environment available (Node + KOA2)
// Router layer const screenshotControllers = require('.. /controllers/puppeteer') const router = new KoaRouter() exports.router = router.post('/api/puppeteer/v1/screenshot', screenshotControllers.api.screenshot)Copy the code
// const service = require('.. /service/puppeteer') const screenshot = (ctx, next) => { return service.api.screenshot(ctx); } exports.api = { screenshot }Copy the code
// service layer 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: 'success ', data: res}}}}Copy the code
// puppeteer = require('puppeteer') 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() SetViewport ({width, {width,}) {{width,}} Height}) await page.goto(url) // go screenshot await page.screenshot({path: Resolve ('./screenshot/${fileName}.png '), // Screenshot save path type: 'PNG ', fullPage: // Execute cos or OSS script to upload image to CDN environment. Close () await browser.close() return '${fileName}.png'}Copy the code
Test service availability
Starting the Node Service
Start the PSOTMAN mock request interface
1. Baidu
View the results
2. The nuggets
{
"url": "https://juejin.cn/",
"width": 720,
"height": 1080,
"tid": 0
}
Copy the code
Well, it doesn’t seem to be a problem
Specific business application
There is a need to generate posters, so what should we do?
2. Write the back-end logic according to the variable ID passed in.
3. Invoke the Node service to obtain the image buffer or image CDN address
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}` } })Copy the code
The result is a solution that smoothes out the differences between operating environments and reduces the failure rate of locally generated images