diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b286074 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +node_modules +*.sh +newrelic* 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/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); }); }; diff --git a/express-server.js b/express-server.js new file mode 100644 index 0000000..1aa8c57 --- /dev/null +++ b/express-server.js @@ -0,0 +1,85 @@ +require('newrelic'); +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.release(); + page.close(); + page = null; + if (portCounter > 13300) { + portCounter = 12300; + } + + + }); + + }); + +// 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() { + 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('?')) + + '?phantomjs=true' + + '#!' + 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..f228488 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "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": "git://github.com/sgentle/phantomjs-node.git#e029778ec4", + "newrelic": "~1.2.0" + } +}