Chrome Puppeteer: Is it better to do everything via JSHandles or through page.execute()?

Viewed 551

I'm writing a fairly script that does some fairly complex work using Puppeteer. However, it probably all be accomplished using ElementHandles in Puppeteer. So, I wanted to know what's the better options:

  1. Just shove a big chunk of code into page.evaluate() and call it a day
  2. Access everything via ElementHandles using functions like page.$()

I would assume that passing these element handles should probably get pretty expensive...

1 Answers

Consider a situation in which you want to access the textContent of an element on a web page using Puppeteer.

It is over 2x faster to handle an element inside page.evaluate() directly than it is to pass the element to the function as an ElementHandle.

Furthermore, it is even faster to pass the pageFunction as a string to page.evaluate() rather than as a function.

You can make an additional micro-optimization by using getElementById() inside page.evaluate() rather than querySelector().

The slowest method would be to use elementHandle.getProperty() in conjunction with elementHandle.jsonValue(). Using this method would require you to wait over 4x longer (compared to the fastest method in this experiment).

You can see the tests performed and the results below:

await page.evaluate('document.getElementById("result").textContent');           // ≈ 0.41 ms ✔
await page.evaluate('document.querySelector("#result").textContent');           // ≈ 0.42 ms
await page.evaluate(() => document.getElementById('result').textContent);       // ≈ 0.42 ms
await page.evaluate(() => document.querySelector('#result').textContent);       // ≈ 0.44 ms
await page.evaluate(result => result.textContent, await page.$('#result'));     // ≈ 0.99 ms
await (await (await page.$('#result')).getProperty('textContent')).jsonValue(); // ≈ 1.69 ms ✘

All of the above tests were run 1,000,000 times, and the average time taken for a single iteration is shown in the comments above.

Therefore, to answer your question, it appears that the least expensive method would be to handle your code within page.evaluate() whenever possible.

Related