Last active
February 19, 2018 03:35
-
-
Save psaia/125b4e6a55761fd27626cf3046a21387 to your computer and use it in GitHub Desktop.
Relay Modern (or anything else) server side rendering for bots.... only.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const fs = require("fs"); | |
const path = require("path"); | |
const express = require("express"); | |
const jsdom = require("jsdom"); | |
const isBot = require("isbot"); | |
const { Script } = require("vm"); | |
const app = express(); | |
const INDEX_FILE = path.normalize(`${__dirname}/../src/www/_index.html`); | |
const APP_PATH = path.normalize(`${__dirname}/../src/www`); | |
const readFile = function(path) { | |
return new Promise((resolve, reject) => { | |
fs.readFile(path, "utf8", (err, data) => { | |
if (err) { | |
reject(err); | |
} else { | |
resolve(data); | |
} | |
}); | |
}); | |
}; | |
// Server up public files from www/. Notice how index.html is _index.html, so it | |
// it doesn't get resolved here. | |
app.use(express.static(APP_PATH)); | |
app.get("*", async function(req, res) { | |
// If we're in bot territory, serve them a rendered html view so they can | |
// scrape away. Otherwise, give the user a good experience. | |
if (isBot(req.headers["user-agent"])) { | |
console.info("Bot detected. Sending html: " + req.headers["user-agent"]); | |
const html = await readFile(INDEX_FILE); | |
// Run scripts, dangerously. | |
const dom = new jsdom.JSDOM(html, { | |
url: process.env.APP_URL + req.originalUrl, | |
pretendToBeVisual: true, | |
resources: "usable", | |
runScripts: "dangerously", | |
beforeParse(window) { | |
// Add any other window specific func's your app may use. | |
window.scrollTo = function() {}; | |
window.alert = function() {}; | |
} | |
}); | |
// You may need to adjust the interval timeout needed for your app | |
// depending on the kinds of things it's doing to the DOM. | |
setTimeout(() => res.send(dom.serialize(), 10); | |
} else { | |
res.sendFile(INDEX_FILE); | |
} | |
}); | |
app.listen(process.env.PORT || 3000); | |
console.info("Environment:", process.env.NODE_ENV); | |
console.info("Listening on port ", process.env.PORT); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment