-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Screenshot action hangs application #555
Comments
At first blush, I’d guess you are likely running into this issue: #493 as a result of using a synchronous For a good primer on managing this, you might want to look into any of: Where there are some good explanations. If that doesn’t help, post back here. If possible, too, try and come up with a simplified test case you can share. That makes understanding the details of the problem much easier. |
@bahlo I had some time today and attempted to reproduce your issue, but could not. Here’s what I tried: var colors = [
'#6699cc',
'#66cc99',
'#cc6699'
]
nightmare.goto('about:blank')
for (var i = 0; i < colors.length; i++) {
nightmare
.wait(2000)
.evaluate(function(color) {
document.body.style.backgroundColor = color;
}, colors[i])
.screenshot(path.resolve(__dirname, i + '.png'))
}
nightmare
.end()
.then(function() {
console.log("Done")
}).catch(function(err) {
console.error(err);
}) (Also, upon looking at this again, I realize you haven’t stumbled over the looping problem at all because you don’t call Anyway, in my very simple and generalized case, everything seems to work. The main reason screenshotting might hang in the way you describe is that when The first thing I’d try is setting If that doesn’t help, I imagine it’s going to be something particular with the page you are attempting to render (maybe something your Otherwise, I’m not sure what to tell you other than to answer any question you have about how and why the screenshotting code works the way it does (which I’m happy to do; it just means I can’t really help you investigate directly). |
@Mr0grog Thank you so much for this. I will try and report back 👍 |
Okay, I tried
|
Hmmmm, you might also try setting Knowing that |
I'm seeing this issue as well. It seems like .screenshot() gets stuck on waiting for "unsubscribing from browser window frames" callback from browser window frame. It unfreezes when I move the mouse around the window. An example page: If I try to take the screenshot for this selector img#uid_0, it seems to be stuck the majority of the time. I also tried the style.zIndex approach with no luck. Good DEBUG |
I moved the complete application from Docker to a dedicated VM and it solved nearly everything. Translating or setting the z-index didn't help though. |
@bahlo : Hi ! What was your config for Docker ? I have the same issue and i would like to resolve it for docker. Thanks |
@GautierT As I said before, I moved away from Docker since it wouldn't work (I found a bug in chromium with some value not high enough in Docker, but don't know which anymore). Works fine in the VM though 👍 |
@bahlo i tried in VM and have the same problem that in docker. When i launch the same script 4-5 times at the same time some of them finish successfully and some of them crash or timeout or get stuck in |
@bahlo : I'm running into this same issue. Can you provide an example of how you manually triggered the callback for |
Try turning your function and loop to be asynchronous, without knowing more of your code something like this would work: function renderFrames * (nightmare, count) {
for (var i = 0; i < count; i++) {
yield nightmare
.screenshot(path.resolve(__dirname, i + '.png'))
.evaluate(nextView)
}
yield nightmare.end()
}
renderFrames(nightmare, 100)
.then(function() {
console.log("Done")
}).catch(function(err) {
console.error(err);
}) Notice the You can use babel to down compile es6 to es5 or if you use a recent enough version of node then you can get it out of the box. |
@bahlo : Nevermind. I found it in your fork ;) https://github.com/bahlo/nightmare/commit/31b17abdf53931cec87cca27b5e2d1f226b611df#diff-bc4eacf94ad1a8e7c9bea8b6b6451251R53 |
Update: The solution that worked for @bahlo (in his fork above) doesn't work for me. In my case, I'm wanting to take a screenshot of a particular rectangle on the page. It appears that manually calling that callback doesn't allow nightmare enough time to move the page to the specified rectangle before taking the screenshot. Still digging for a solution. |
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.
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).
Anyone here experiencing timeouts may want to give the #927 a try. There’s also second approach to solving this over on https://github.com/mr0grog/nightmare/tree/screenshot-with-offscreen-rendering that you might give a try. |
@Mr0grog : thanks a ton for your effort! |
@mackermedia Awesome!
That sounds like a problem. It shouldn’t be related to the window size bug; that was a problem with my experimental If you can come up with a way to reproduce it reliably, would you please post it on that PR or as an issue (if the PR gets merged in the mean time)? |
I fixed the problem using a timeout to move the window frame by few pixels. nightmare
// fix browser hanging on screenshot
.evaluate(()=> setTimeout(()=> window.scrollBy(0,5), 1000))
.screenshot(screenshotPath) By the time the window hangs, it'll move and get out the stuck situation. |
@casesandberg I guess it’s not clearly linked, but #945 is the PR for this issue. It’s been solved if only someone with privileges would review and merge (or give feedback). |
(That is to say, it seems like it would make sense to keep this open since it’s tracking an actual PR) |
Ah, my bad, I didn't see that it was tracking with a PR. |
when is apply this fix? |
I wanted to leave a little note here that I had this same issue while running nightmare in docker and was able to google enough to find that the docker shared memory is 64mb by default and is the cause of this and a few other things changing it to 128mb fixed it but you may need more or less I submitted #1570 to add more info onto the readme. |
Hey guys, thank you for this library, I'm really loving it (especially in comparison with the PhantomJS backend).
I'm creating screenshots of a page with multiple views with the following code.
The views are changed in the
nextView
function.This works great on most pages, but it hangs on a specific page (I'm sorry I can't disclose the contents).
Here is a part of the log:
As you can see, the screenshot before renders nicely, but the last one does not seem to do anything.
The
requestFrame
function doesn't seem to call its callback.Do you have any tips for me to debug this? Setting a
waitTimeout
doesn't help since I'm not waiting.Update: Okay, I tried again with
show: yes
and manually triggered a re-render and it worked. Maybe I'll try to click on something to trigger that render manually every time.Update 2: Since it's only waiting for change after the
screenshot
action, callingscrollTo
orclick
before doesn't help.Update 3: I tested it and the callback doesn't get called in the
requestFrame
function for this screenshot (all the other shots are working fine).Update 4: I'm just calling the callback directly in
requestFrame
which is bad, but works for me. Gonna leave this issue open though.The text was updated successfully, but these errors were encountered: