Skip to content Skip to sidebar Skip to footer

React With Google Chromes Puppeteer

Trying to render a react component with chrome puppeteer running on my Node.js environment I’m having following problem: logging element gives me in the headless chrome console

Solution 1:

.evaluate does not return a dom element. And, you are trying to modify the elements in different context. The page in the browser window and the context you have in your nodeJS is absolutely different.

Here is a different way to deal with React and Puppeteer. First, I have an entry file where I export the function to window.

By doing this, I can access it from the browsers context easily. Instead of window, you can actually export it and try expose-loader and so on. I'll use webpack to build it.

importReactfrom'react';
import { render } from'react-dom';

functionHello() {
  return<h1>Hello from React</h1>;
}

functionrenderIt(domNode) {
  render(<Hello />, domNode);
}

window.renderIt = renderIt;

On the webpack config,

const webpack = require('webpack');

const loaders = [
  {
    test: /\.jsx?$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query: {
      presets: ['babel-preset-es2015', 'babel-preset-react'],
      plugins: []
    }
  }
];

module.exports = {
  entry: './entry.js',
  output: {
    path: __dirname,
    filename: 'bundle.js',
    libraryTarget: 'umd'
  },
  module: {
    loaders: loaders
  }
};

Now whenever I run webpack, it'll create a bundle.js file for me. Now let's have a puppeteer file,

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto('https://github.com');
  await page.addScriptTag({ path: require.resolve('./bundle.js') });
  await page.evaluate(() => {
    renderIt(document.querySelector('div.jumbotron.jumbotron-codelines > div > div > div > h1'));
  });
  await page.screenshot({ path: 'example.png' });
  await browser.close();
})();

As you can see, I'm using the renderIt function that I exposed to window earlier. And when I run it, here is the result,

enter image description here

Sweet! Hello from react :)

Oh! And if it fails to execute script on the page due to CORS issue, you can inject it instead using the old injectFile function, until they fix their addScriptTag function, or remove deprecation from injectFile.

/**
 * injects file to puppeteer page context
 * @param  {Object} page     context where to execute the script
 * @param  {String} filePath path of specific script
 * @return {Promise}         Injects content to page context
 */const fs = require('fs');

asyncfunctioninjectFile(page, filePath) {
  let contents = awaitnewPromise((resolve, reject) => {
    fs.readFile(filePath, 'utf8', (err, data) => {
      if (err) returnreject(err);
      resolve(data);
    });
  });
  contents += `//# sourceURL=` + filePath.replace(/\n/g, '');
  return page.mainFrame().evaluate(contents);
}

// usage: await injectFile(page, require.resolve('FILE PATH'));// export it if you want to keep things seperate

Post a Comment for "React With Google Chromes Puppeteer"