Today I've been working on a solution to generate website screenshots for one of my projects. After diving into various topics on the net I came to the conclusion that using PhantomJS was probably my best choice.
Since I was running a vagrant (Homestead) local server, I required the package from jonnyw/php-phantomjs
(https://packagist.org/packages/jonnyw/php-phantomjs) into an existing project and kicked of with a basic script:
$client = Client::getInstance();
$client->debug(true);
$client->setBinDir('/home/admin/domains/domain.com/public_html/bin/');
$request = $client->getMessageFactory()->createCaptureRequest('http://www.domain.com/preview/H/31', 'GET');
$request->setCaptureFile('/home/admin/domains/domain.com/public_html/screens/sample.jpg');
$request->setViewportSize(1366, 768);
$response = $client->getMessageFactory()->createResponse();
$client->send($request, $response);
It took me a little while before the code stopped throwing warnings, but in the end the code worked like it should! I then went on to migrate the code to the project it was supposed to be in, which is written in procedural php code. I required the package, included the autoloader en executed exactly the same command as on my Vagrant environment.
The result was a bit different: a heading wasn't showing and the background image wasn't showing either. I might need to add that the heading has a custom font attached to it.
A few weeks ago I've set up a server for a client that required Laravel, I also required the package on that server and executed the same code. At first I was getting some random white pages but eventually I got the screenshot I expected. I can live with the fact that something a screenshot turns out white, as long as they come up right eventually.
Then I went back to the code this script was intended for and gave it a few more shots. But the results kept being white or missing some elements (custom font title + background image). My last try was to change the capture.proc
file, I added a setTimeout function before rendering the image. That did fix one problem: I haven't had any white images since, but didn't fix the most important problem: the missing heading and background.
I've double checked all bin files, they all use version 1.9.7 of PhantomJS so I doubt there's an issue there. But can there be a difference in server configuration (or PHP version) that stops the script from giving the right result?
Just to give as much info as possible, the problem server is on the lowest PHP version:
It really looks like you should wait a little after loading the page and before taking the screenshot. Single-page applications and Webfonts usually take a little to load and render, whereas PhantomJS is a little eager in firing the load finished event and reporting that the load has finished.
You can squeeze in a $request->setDelay(2);
between ...->createCaptureRequest(..)
and $request->setCaptureFile(...)
. See documentation.
Using a static delay is not very robust. It's better to use a waitFor()
function which triggers as soon as the condition (such as a specific page element appears on the page) is fulfilled. php-phantomjs doesn't provide such a functionality through it's API, but you can use a PhantomJS script directly which could do this sort of thing. See the documentation.