0

index.js

import puppeteer from 'puppeteer'

// Route 1 # Google
fastify.get('/google', async (request, reply) => {

   const browser = await puppeteer.launch({
       headless,
       args: ['--no-sandbox'],
   })

   const page = await browser.newPage()
   await page.goto('https://google.com', { waitUntil: 'networkidle2' })

  const data = await page.evaluate(() => {
  const body = document.querySelector('body').textContent
      return { body }
  })
})

// Router 2 # Bing
fastify.get('/bing', async (request, reply) => {

   const browser = await puppeteer.launch({
       headless,
       args: ['--no-sandbox'],
   })

   const page = await browser.newPage()
   await page.goto('https://bing.com', { waitUntil: 'networkidle2' })

  const data = await page.evaluate(() => {
  const body = document.querySelector('body').textContent
      return { body }
  })
})

// Run the server!
const start = async () => {
  try {
    await fastify.listen({ port })
    console.log(' Fastify Server Listening on Port 3000')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

start()

Is there a way to use browser and page globally? Above example each router generate browser every single request. I think it is not proper use case - will occurr memory leak I guess. Is there a way initiate browser on first launching server and reuse it each router?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
ton1
  • 7,238
  • 18
  • 71
  • 126
  • 1
    See [the example at the bottom of this post](https://stackoverflow.com/a/67910262/6243352). It's for Express but it's virtually the same as fastify. I'm pretty sure you'll want to make a new page per request, though. Otherwise, what's supposed to happen if two clients connect at the same time? Eventually, you might want a queue or puppeteer-cluster to avoid _too_ many clients connecting at once. As an aside, you can use `await page.content()` rather than the whole `await page.evaluate(() => {` thing. – ggorlen Mar 27 '23 at 14:07

1 Answers1

2

You can use decorator for this: https://www.fastify.io/docs/latest/Reference/Decorators/#decorators

fastify.get('/bing', async function foo (request, reply) {

   const browser = fastify.browser()
   // or const browser = this.browser() when you use named handler function

   const page = await browser.newPage()
   await page.goto('https://bing.com', { waitUntil: 'networkidle2' })

  const data = await page.evaluate(() => {
  const body = document.querySelector('body').textContent
      return { body }
  })
})


const start = async () => {
  try {
   const browser = await puppeteer.launch({
       headless,
       args: ['--no-sandbox'],
   })

    fastify.decorate('browser', function () {
      return browser
    })
    await fastify.listen({ port })
    console.log(' Fastify Server Listening on Port 3000')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

As suggested in the question's comments, beware of multiple requests and too many tabs opened.

Manuel Spigolon
  • 11,003
  • 5
  • 50
  • 73