├── .jscsrc ├── README.md ├── index.js └── package.json /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "crockford", 3 | "disallowTrailingComma": null, 4 | "requireMultipleVarDecl": null 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # phearjs-express 2 | 3 | PhearJS (http://phear.io) is a prerender for client-side dynamic web pages. To 4 | serve prendered versions of your website to bots like the ones from Yahoo, Bing, 5 | Yandex, Google and so forth you can use this Express middleware. When a bot is 6 | detected the middleware will serve a prerendered version of your page. 7 | 8 | ## Installation 9 | 10 | You should have a PhearJS instance running somewhere. For setup instructions please refer to these [installation instructions](https://github.com/Tomtomgo/phearjs/blob/master/INSTALLATION.md). 11 | 12 | If you have that running, install phearjs-express middleware: 13 | 14 | ``` 15 | npm install phearjs-express 16 | ``` 17 | 18 | ## Usage 19 | 20 | ### Default usage 21 | 22 | Add the following code to your Express app and every request will automatically 23 | be served prerendered only if necessary. 24 | 25 | var prerender = require('phearjs-express'); 26 | app.use(prerender({})); 27 | 28 | #### Custom PhearJS endpoint 29 | 30 | var prerender = require('phearjs-express'); 31 | app.use(prerender({phear_url: http://192.168.1.42:1337})); 32 | 33 | #### Custom user agent for PhearJS 34 | 35 | var prerender = require('phearjs-express'); 36 | app.use(prerender({phear_agent: 'MyVerySpecialPhearJSBot/0.1.2'})); 37 | 38 | ## Bugs / contribute 39 | 40 | If something doesn't work as expected or breaks, please create an 41 | [issue](https://github.com/Tomtomgo/phearjs-express/issues). When you feel like 42 | fixing an issue or improving this middleware, feel free to open an issue and 43 | create a pull request! 44 | 45 | I've used the [JSCS](http://jscs.info/) linter, so for bonus points, lint :) -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | var http = require('http'); 6 | var url = require('url'); 7 | 8 | function is_robot(user_agent) { 9 | var bots_list = [/baiduspider/i, /facebookexternalhit/i, /embedly/i, /quora/i, /link/i, /preview/i, /outbrain/i, /pinterest/i, /vkShare/i, /W3C_Validator/i]; 10 | // Check for the simple 'bot' string or from the list of bots from an array. 11 | // Some bots from several services do not have the word bot in them. 12 | return user_agent.toLowerCase().indexOf('bot') > -1 || bots_list.some(function (bot) { return bot.test(user_agent); }); 13 | } 14 | 15 | function is_phear(user_agent, phear_agent_identifier) { 16 | // Check that the user agent is a PhearJS agent. 17 | if (phear_agent_identifier === undefined) { 18 | phear_agent_identifier = 'phear'; 19 | } 20 | return user_agent.toLowerCase().indexOf(phear_agent_identifier) > -1; 21 | } 22 | 23 | function construct_url(options, req) { 24 | var phear_url; 25 | var requested_url; 26 | 27 | requested_url = url.format({ 28 | protocol: req.protocol, 29 | host: req.get('host'), 30 | pathname: req.originalUrl, 31 | }); 32 | 33 | if (options.phear_url !== undefined) { 34 | phear_url = url.parse(options.phear_url); 35 | } else { 36 | phear_url = url.parse('http://localhost:8100'); 37 | } 38 | 39 | phear_url.query = { 40 | fetch_url: requested_url, 41 | raw: 1, 42 | }; 43 | 44 | return url.format(phear_url); 45 | } 46 | 47 | function prefetch(options, req, res, next) { 48 | if (!is_robot(req.headers['user-agent']) || 49 | is_phear(req.headers['user-agent'], options.phear_agent)) { 50 | // continue if this is not a robot 51 | next(); 52 | } else { 53 | http.get(construct_url(options, req), function (inner_res) { 54 | var phear_response = ''; 55 | 56 | inner_res.on('data', function (data) { 57 | phear_response += data; 58 | }); 59 | 60 | inner_res.on('end', function () { 61 | res.write(phear_response); 62 | res.end(); 63 | }); 64 | }).on('error', function () { 65 | // In case of an error we fall back to regular no prerendering behaviour 66 | next(); 67 | }); 68 | } 69 | } 70 | 71 | module.exports = function (options) { 72 | return prefetch.bind(null, options); 73 | }; 74 | 75 | })(); 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phearjs-express", 3 | "version": "0.1.3", 4 | "homepage": "https://github.com/Tomtomgo/phearjs-express", 5 | "description": "An Express middleware for PhearJS. Serves prerendered pages to bots and search engines.", 6 | "keywords": ["phearjs", "phantomjs", "express", "middleware", "seo", "prerender", "ajax"], 7 | "author": { 8 | "name": "Tom Aizenberg" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/Tomtomgo/phearjs-express/issues" 12 | }, 13 | "repository" : { 14 | "type" : "git", 15 | "url" : "https://github.com/Tomtomgo/phearjs-express.git" 16 | } 17 | } 18 | --------------------------------------------------------------------------------