I'm taking screenshots of HTML pages using PhantomJS and I've been using my code (see below) successfully for over a year. However, a while ago I found out that the version I use (1.9.8) doesn't support web fonts: PhantomJS not rendering screenshots with webfonts?.
In an effort to solve this I installed PhantomJS 2.0.0. This solved the font issue, but also increased the loading time of my script considerably (note that my script is 100% the same for both):
PhantomJS 1.9.8 (Windows): ~1,5 sec
PhantomJS 2.0.0 (Windows): ~2,25 sec
Disabling web fonts includes resulted in a ~0,2 sec performance increase for both versions.
I also benchmarked http://google.com/:
PhantomJS 1.9.8 (Windows): ~1,9 sec
PhantomJS 2.0.0 (Windows): ~2,6 sec
So it's unlikely to be related to my HTML or the fact that I use local HTML files. Following this observation I did some research and found the following options that don't work for me:
- PhantomJS not rendering screenshots with webfonts? - removing
local('...')
from the@font-face
is not an option since I load my fonts through Google - https://github.com/ariya/phantomjs/issues/13117 - compressing/decompressing both executables
- http://arunoda.me/blog/phantomjs-webfonts-build.html - sound perfect but I'm stuck with Windows while only Linux and OSX are offered
TL;DR Does anyone have any ideas on how I can improve PhantomJS 2.0.0 performance? Code improvements, PhantomJS tips, Windows builds (e.g. 1.9.x web font friendly) - all are welcome.
Code
Loading the font in the <head>
tag of my local HTML file (looks fine when I open it in my browser):
<link href="https://fonts.googleapis.com/css?family=Roboto:500" rel="stylesheet" type="text/css">
Calling the PhantomJS PHP helper function:
$output = Image::getPageImage($pathToLocalHTMLFile);
PhantomJS PHP helper function:
class Image {
public static function getPageImage($page, $options = array(), $js = null) {
// Prepare the page path when needed
if (strpos($page, 'http') !== 0) $page = 'file:///' . $page;
// Prepare the PhantomJS directory
$phantomDir = DIR_LIB . 'phantomjs' . DIR_SEPARATOR;
// Add the PhantomJS directory to the PATH
addPath($phantomDir);
// In case no Javascript processing file is given, use the default
if (is_null($js)) $js = $phantomDir . 'phantom.js';
// Prepare the PhantomJS call
$exec = 'phantomjs --ignore-ssl-errors=true ' . $js . ' ' . escapeshellarg($page);
// Prepare the PhantomJS options
foreach ($options as $option) {
$exec .= ' ' . escapeshellarg($option);
}
// Call PhantomJS
exec($exec, $output);// . ' 2>&1', $output, $errorMsg
// Decode and return the image data
return ($output ? base64_decode(reset($output)) : false);
}
}
phantom.js in the PhantomJS directory:
args = require('system').args;
page = require('webpage').create();
if (typeof args[2] !== undefined) {
page.viewportSize = {
width: args[2],
height: (typeof args[3] === undefined ? args[2] : args[3])
};
}
page.open(args[1], function() {
var width = page.evaluate(function() {
return document.body.offsetWidth;
});
var height = page.evaluate(function() {
return document.body.offsetHeight;
});
page.clipRect = {top: 0, left: 0, width: width, height: height};
var base64 = page.renderBase64('png');
console.log(base64);
phantom.exit();
});
My server environment is Windows Server 2008 R2 Standard with IIS7.5 + FastCGI running PHP 5.4. Like I mentioned before - the only variable in my benchmarks is the PhantomJS version.
Thanks for the help!