1

I'm trying to create an image snaphot of my website using node-weshot which depends on phantomjs. It work as expected on my local machine, but when I deploy it on a live server. It just keeps firing the callback saying that image is generated. But underneath, the process is still generating the image. (i.e) The filename is generated, but it has no size and contents. After 10 minutes the file will be populated with the image data. However the fonts did not render correctly.

here is the screenshot: no fonts

and heres my webshot code:

var options = {
  screenSize: {
   width: 403,
   height: 403
  },
  shotSize: {
    width: 403,
   height: 403
  },
  script: function() {
    $(function() {
      window.callPhantom('takeShot');
    });
  },
  takeShotOnCallback: true
};

webshot(baseUrl+frame_url, path, options, function(err) {
    if(err){
      return res.json({ok:false, error:err.error || err});
    }
    return res.json({image:baseUrl+img,ok:true});
  });

So technically I have 2 problems here:

  1. Webshot returns the callback even though the image generation is not finished yet.
  2. The generated image does not render the fonts correctly. (Im using Google fonts here).

Is there any of fixing the issue? I can see that this is related to How do you take a screenshot of an angularjs app?

Or are there any good alternatives to node-webshot and phantomjs?

Community
  • 1
  • 1
Ryan
  • 151
  • 3
  • 11

1 Answers1

1

I'm pretty new to webshot and phantom myself, but it seems you are providing an anonymous function there, which will execute as soon as possible REGARDLESS of whether your images are generated or not. If you want to wait for all the images to load before calling window.callPhantom, you may want to try something like

script: function() {
    window.onload = function() {
        if (window.callPhantom === 'function') {
            window.callPhantom('takeShot');
        }
    };
},

window.onload will only be called once all the assets on the page have been loaded. It probably worked fine on your local machine because the assets were loaded much faster, BEFORE your anonymous function was called.

EDIT: I tried this (and other similar things) myself: it DOES NOT WORK. I've also tried putting the callPhantom code on the client side:

<script>
    window.onload = function() {
        if (typeof(window.callPhantom) === 'function') {
            window.callPhantom('takeShot');
        }
    };
</script>

ALSO does not work (it doesn't break the page, though).

I'll keep at this and post my findings here, even if I end up abandoning webshot all together.

EDIT: So two things -- firstly, having re-read the question this has more to do with fonts rather than images (meaning probably a duplicate of Some issues capturing web page image with, node-webshot). Secondly, it turns out the reason behind why my webshot setup wasn't working because of snapping timing, but SSL issues on phantom level (PhantomJS failing to open HTTPS site).

I feel like I've been barking up the wrong tree for the past few days, but it feels good to finally get to the bottom of things. One lesson (among many) I learned in this ordeal is that any problems you encounter using webshot may be at phantom-level. Below is the code I used to view phantom's network activities (modified the pizza example from the module). Just copy it into a js file and run it with phantom (> phantom test.js)

var page = require('webpage').create(),
    url = 'http://some.url.you.want.to.test';

page.onResourceRequested = function(request) {
  console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
  console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
page.onResourceError = function(resourceError) {
  console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
  console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.open(url, function (status) {
    if (status !== 'success') {
        console.log('Unable to access network');
    } else {
        console.log(status);
    }
    phantom.exit();
});
Community
  • 1
  • 1
jang0
  • 65
  • 6
  • I think that the load status of web fonts does not trigger `$.load(func)` which is the same as `$(func)` which OP did. – Artjom B. Oct 23 '14 at 15:11
  • Yeah I'm still fighting to get the logic to work. The approach as a whole seems either unreliable or cumbersome beyond practicality to implement. – jang0 Oct 23 '14 at 18:55
  • In your edit summary you've written that jQuery doesn't play nicely with webshot. Can you expand on that in your post? – Artjom B. Oct 23 '14 at 21:26
  • I've had cases (and also found statements from other people) where what is snapped by webshot does not incorporate results from jQuery code. Although I think it's likely webshot was snapping before all the JS code was executed (whether it's jQuery or not), I wanted to reduce as many uncertainties as possible. – jang0 Oct 24 '14 at 22:31