How to make Puppeteer work with a ReactJS application on the client-side

前端 未结 1 1441
别跟我提以往
别跟我提以往 2020-12-03 15:51

I am fairly new to React and I am developing an app which will take actual screenshots of a web page and the app can draw and add doodles on top of the screenshot taken. I i

1条回答
  •  再見小時候
    2020-12-03 16:18

    Your React.js application runs on the client-side (in the browser). Puppeteer cannot run inside that environment as you cannot start a full browser inside the browser.

    What you need is a server which does that for you. You could ether offer a HTTP endpoint (option 1) or expose your puppeteer Websocket (option 2):

    Option 1: Provide a HTTP endpoint

    For this option, you setup a server which handles the incoming request and runs the task (making a screenshot) for you:

    server.js

    const puppeteer = require('puppeteer');
    const express = require('express');
    
    const app = express();
    
    app.get('/screenshot', async (req, res) => {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(req.query.url); // URL is given by the "user" (your client-side application)
        const screenshotBuffer = await page.screenshot();
    
        // Respond with the image
        res.writeHead(200, {
            'Content-Type': 'image/png',
            'Content-Length': screenshotBuffer.length
        });
        res.end(screenshotBuffer);
    
        await browser.close();
    })
    
    app.listen(4000);
    

    Start the application with node server.js and you can now pass the URL to your server and get a screenshot back from your server: http://localhost:4000/screenshot?url=https://example.com/

    The response from the server could then be used as as the source of an image element in your application.

    Option 2: Exposing the puppeteer Websocket to the client

    You could also control the browser (which runs on the server) from the client-side by by exposing the Websocket.

    For that you need to expose the Websocket of your server like this:

    server.js

    const puppeteer = require('puppeteer');
    
    (async () => {
        const browser = await puppeteer.launch();
        const browserWSEndpoint = browser.wsEndpoint();
        browser.disconnect(); // Disconnect from the browser, but don't close it
        console.log(browserWSEndpoint); // Communicate the Websocket URL to the client-side
        // example output: ws://127.0.0.1:55620/devtools/browser/e62ec4c8-1f05-42a1-86ce-7b8dd3403f91
    })();
    

    Now you can control the browser (running on the server) form the client-side with a puppeteer bundle for the client. In this scenario you could now connect to the browser via puppeteer.connect and make a screenshot that way.

    I would strongly recommend using option 1, as in option 2 you are fully exposing your running browser to the client. Even with option 1, you still need to handle user input validation, timeouts, navigation errors, etc.

    0 讨论(0)
提交回复
热议问题