From 9a0b289fccd3f630c1c483164266a513a636618f Mon Sep 17 00:00:00 2001 From: Chris Esplin Date: Fri, 8 Nov 2013 15:11:49 -0700 Subject: [PATCH 1/7] Adding an Express server as a convenient Node wrapper. --- .gitignore | 2 ++ README.md | 11 +++++++ express-server.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 29 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 .gitignore create mode 100644 express-server.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a1537b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +node_modules diff --git a/README.md b/README.md index a7de44d..d6c380d 100644 --- a/README.md +++ b/README.md @@ -113,4 +113,15 @@ if ($args ~ _escaped_fragment_) { # Proxy to PhantomJS instance here } ``` + +Running using Node and Express +============================== + +Running PhantomJS jobs as a daemon on the server can be very tricky. One solution is to wrap PhantomJS in a regular Node server. The Node server can be run as a daemon using [forever](https://github.com/nodejitsu/forever) + +To use Express, first ```npm install``` to retrieve all Node dependencies. Next run something like ```node express-server.js 8888 http://myserver.com/``` or ```forever start express-server.js 8888 http://myserver.com/``` + +The Express server behaves very similarly to angular-seo-server.js; however, it does not at this time take any options as arguments. All PhantomJS options are hardcoded. + [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/3a55c16a191c4c8222beddcf429c2608 "githalytics.com")](http://githalytics.com/steeve/angular-seo) + diff --git a/express-server.js b/express-server.js new file mode 100644 index 0000000..e2b1d56 --- /dev/null +++ b/express-server.js @@ -0,0 +1,74 @@ +var app = require('express')(), + port = process.argv[2], + prefix = process.argv[3], + phantom = require('phantom'), + noCache = '--disk-cache=no', + noSSL = '--ignore-ssl-errors=true', + noImages = '--load-images=false', + allowRemote = '--local-to-remote-url-access=yes', + REGEX = /_escaped_fragment_=([^&]+)/, + portCounter = 12300; + +var parse_qs = function(s) { + var fragment = s.match(REGEX); + if (fragment.length > 1) { + return fragment[1]; + } + +}; + +var renderHtml = function(url, cb) { + portCounter += 1; + + console.log('PhantomJS query: ' + url + ' using port ' + portCounter + '.'); + + phantom.create(noCache, noSSL, noImages, allowRemote, {port: portCounter}, function (ph) { + ph.createPage(function (page) { + + page.set('onLoadFinished', function() { + page.get('content', function (content) { + cb(content); + page.close(); + if (portCounter > 13300) { + portCounter = 12300; + } + }); + + }); +// page.onConsoleMessage = function(msg, lineNum, sourceId) { +// console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); +// }; + page.set('onInitialized', function() { + page.evaluate(function() { + setTimeout(function() { + window.callPhantom(); + }, 10000); + }); + }); + + page.open(url); + }) + }); + + + +}; + +app.get('/', function (req, res) { + var route = parse_qs(req.url), + callback = function (html) { + res.send(html); + }, + url = prefix + + req.url.slice(1, req.url.indexOf('?')) + + '#!' + decodeURIComponent(route); + + renderHtml(url, callback); + +}); + +app.listen(port); + + +console.log('Listening on ' + port + '...'); +console.log('Press Ctrl+C to stop.'); diff --git a/package.json b/package.json new file mode 100644 index 0000000..1c4a6c1 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "angular-seo", + "version": "0.0.0", + "description": "PhantomJS-based SEO tools for Angular.", + "main": "express-server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/deltaepsilon/angular-seo.git" + }, + "keywords": [ + "angular", + "seo", + "phantomjs", + "phantomjs-node", + "node" + ], + "author": "Christopher Esplin (http://christopheresplin.com/)", + "license": "BSD-2-Clause", + "bugs": { + "url": "https://github.com/deltaepsilon/angular-seo/issues" + }, + "dependencies": { + "express": "~3.4.4", + "phantom": "~0.5.4" + } +} From 3c529a3183ffaecb7ef46b79e7872eda2343eb77 Mon Sep 17 00:00:00 2001 From: Christopher Esplin Date: Fri, 8 Nov 2013 22:33:54 +0000 Subject: [PATCH 2/7] Ignoring .sh files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7a1537b..24bf945 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea node_modules +*.sh From aae89b7ddd62601c796a8ad625e266ba784a8c77 Mon Sep 17 00:00:00 2001 From: Chris Esplin Date: Sat, 9 Nov 2013 15:44:58 -0700 Subject: [PATCH 3/7] Check that callPhantom is actually a function before calling it. --- angular-seo-server.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/angular-seo-server.js b/angular-seo-server.js index c898875..e73e9e9 100644 --- a/angular-seo-server.js +++ b/angular-seo-server.js @@ -34,7 +34,9 @@ var renderHtml = function(url, cb) { page.onInitialized = function() { page.evaluate(function() { setTimeout(function() { + if (typeof window.callPhantom === 'function') { window.callPhantom(); + } }, 10000); }); }; From b4eaa8da37a35fb7e041b1fb7c8812f26be4a38f Mon Sep 17 00:00:00 2001 From: Chris Esplin Date: Wed, 20 Nov 2013 07:52:25 -0700 Subject: [PATCH 4/7] Adding phantomjs query param for better front-end handling. --- express-server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/express-server.js b/express-server.js index e2b1d56..87ab0e9 100644 --- a/express-server.js +++ b/express-server.js @@ -61,6 +61,7 @@ app.get('/', function (req, res) { }, url = prefix + req.url.slice(1, req.url.indexOf('?')) + + '?phantomjs=true' + '#!' + decodeURIComponent(route); renderHtml(url, callback); From c07b97968c32a8f4c23e5012673745d191ebc6f6 Mon Sep 17 00:00:00 2001 From: Christopher Esplin Date: Wed, 11 Dec 2013 15:10:30 +0000 Subject: [PATCH 5/7] Adding newrelic agent. --- .gitignore | 1 + express-server.js | 1 + package.json | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 24bf945..b6d3bc7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea node_modules *.sh +newrelic.js diff --git a/express-server.js b/express-server.js index 87ab0e9..6c7af73 100644 --- a/express-server.js +++ b/express-server.js @@ -1,3 +1,4 @@ +require('newrelic'); var app = require('express')(), port = process.argv[2], prefix = process.argv[3], diff --git a/package.json b/package.json index 1c4a6c1..7f2005e 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "express": "~3.4.4", - "phantom": "~0.5.4" + "phantom": "~0.5.4", + "newrelic": "~1.2.0" } } From 03395619530ba45879905298cf7f8b617928a6a1 Mon Sep 17 00:00:00 2001 From: Chris Esplin Date: Fri, 13 Dec 2013 17:53:01 -0700 Subject: [PATCH 6/7] Upgrading to the patched version of phantomjs-node. There was a memory leak that they finally fixed. --- .gitignore | 2 +- express-server.js | 11 ++++++++--- package.json | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index b6d3bc7..b286074 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .idea node_modules *.sh -newrelic.js +newrelic* diff --git a/express-server.js b/express-server.js index 6c7af73..84f29c5 100644 --- a/express-server.js +++ b/express-server.js @@ -36,9 +36,14 @@ var renderHtml = function(url, cb) { }); }); -// page.onConsoleMessage = function(msg, lineNum, sourceId) { -// console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); -// }; + +// page.onConsoleMessage = function(msg, lineNum, sourceId) { +// console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); +// }; +// page.onResourceReceived = function(response) { +// console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response)); +// }; + page.set('onInitialized', function() { page.evaluate(function() { setTimeout(function() { diff --git a/package.json b/package.json index 7f2005e..f228488 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "express": "~3.4.4", - "phantom": "~0.5.4", + "phantom": "git://github.com/sgentle/phantomjs-node.git#e029778ec4", "newrelic": "~1.2.0" } } From a258fd6432f0756314793f95330617be40142e55 Mon Sep 17 00:00:00 2001 From: Chris Esplin Date: Tue, 11 Feb 2014 14:44:09 -0700 Subject: [PATCH 7/7] Attempting to kill the page. --- express-server.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/express-server.js b/express-server.js index 84f29c5..1aa8c57 100644 --- a/express-server.js +++ b/express-server.js @@ -29,10 +29,14 @@ var renderHtml = function(url, cb) { page.set('onLoadFinished', function() { page.get('content', function (content) { cb(content); + page.release(); page.close(); + page = null; if (portCounter > 13300) { portCounter = 12300; } + + }); });