Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nightmare freezes on either evaluate() or screenshot() #736

Closed
ryanvincent29 opened this issue Jul 27, 2016 · 4 comments
Closed

Nightmare freezes on either evaluate() or screenshot() #736

ryanvincent29 opened this issue Jul 27, 2016 · 4 comments

Comments

@ryanvincent29
Copy link

I am working on moving from Phantom JS to Nightmare in an effort to get more CSS compatibility on my pages.

As a high-level view, my Nightmare instance lives inside a Docker container and listens for data to be pushed onto a queue. Once that data is pushed, I pull some data (including a string of HTML) out of the queue, alter the page a bit using Cheerio, and then turn the data into a HTML Data URL.

Then, I goto the data url, use a couple of evaluate functions, scroll the page, and take a screenshot.

Here is a condensed version of my code:

function callNightmare(nightmare, html, data) {
  return new Promise(function(resolve, reject){
    var imageLoc = "./screenshot" + data.randomGuid + '.png';
    nightmare
      .userAgent(data.agentString)
      .goto(html)
      .wait()
      .then(function() {
        //remove scrollbar from image
        return nightmare.evaluate(function() { 
          var s = document.styleSheets[0];
          s.insertRule('::-webkit-scrollbar { display:none; }'); }
      })
      .then(function() {
        return nightmare.viewport(data.width, data.height);
      })
      .then(function() {
        return nightmare.inject('js', './localScript.js');
      })
      .then(function() {
        return nightmare.evaluate(getScrollPositionFromPage);
      })
      .then(function(scrollPosition) {
        return nightmare.scrollTo(scrollPosition.top, scrollPosition.left);
      })
      .then(function() {
        return nightmare.evaluate(fillInputsOnPageWithValues);
      })
      .then(function(){
        return nightmare.screenShot(imageLoc);
      })
      .then(function() {
        return nightmare.end();
      })
      .then(function() {
        resolve(imageLoc);
      })
      .catch(function(err) { 
        reject(err); 
      })
  });
}

However, my script will occasionally lock up during various evaluate functions, or during the screenshot function. Other times, the script runs successfully. I have tried this on various websites with the same results.

I can't pinpoint anything in the script that is causing this issue, and I didn't know if any of you had any thoughts on the problem?

@rosshinkley
Copy link
Contributor

Silly question: have you tried running with DEBUG=* to see if that has any helpful information?

@rosshinkley
Copy link
Contributor

(Also: Possibly related to #405.)

@ryanvincent29
Copy link
Author

Yeah, I run it with DEBUG=*, it outputs 2 lines indicating the initialization of Nightmare, but then I stop getting output from that debug path for the remainder of the program.

Mr0grog added a commit to Mr0grog/nightmare that referenced this issue Dec 16, 2016
Since the initial implementation of `FrameManager`, Electron added an API for Chromium's remote debugging protocol. One of the debugger's capabilities is to visually highlight a portion of the page. This change uses that functionality to force a new frame to be rendered. This is much more reliable than the way Nightmare currently tries to force new frames to render by fiddling around with the DOM (see issues segment-boneyard#555, segment-boneyard#736, segment-boneyard#809). It also has the benefit of not doing anything page content can observe, ensuring that any JS or CSS won't modify the page in response to Nightmare's attempt to take a screenshot.

In future versions of the protocol, it will be possible to directly capture an image of the page, but that feature is still experimental (so it could be removed) and Electron does not yet support it anyhow. Something to keep in mind for future changes, though.

This is an alternative solution to the one in 53dee8a (currently on the `screenshot-with-offscreen-rendering` branch). That method (using Electron's new "offscreen" rendering mode) is *much* faster than this and vastly simplifies the code, but has more ways it can fail.
Mr0grog added a commit to Mr0grog/nightmare that referenced this issue Dec 16, 2016
Sometime mid-year, Electron added support for "offscreen" rendering (it still shows a window, but the whole rendering pipeline is a bit different). When this mode is enabled, the rendered view can be explicitly invalidated, which is *much* better and more reliable than the way Nightmare currently tries to force new frames to render by fiddling around with the DOM (see issues segment-boneyard#555, segment-boneyard#736, segment-boneyard#809).

This isn't without its downsides; it doesn't work with forced device scale factors and it renders differently than with native system rendering (e.g. text rendering will be slightly different).
@rosshinkley
Copy link
Contributor

Considering this fixed with #927. If you're still having this problem with that change, feel free to reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants