Skip to content

Instantly share code, notes, and snippets.

@loganpowell
Forked from lovetingyuan/jsdom-prerender.js
Created April 27, 2023 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganpowell/4de527fac33afc64b0253d52d8777aef to your computer and use it in GitHub Desktop.
Save loganpowell/4de527fac33afc64b0253d52d8777aef to your computer and use it in GitHub Desktop.
use jsdom to prerender simple page.
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const path = require('path')
const fetch = require('node-fetch')
const finalhandler = require('finalhandler')
const http = require('http')
const serveStatic = require('serve-static')
function createServer (port, root = path.join(__dirname, 'dist')) {
const serve = serveStatic(root)
const server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
server.listen(port)
return server
}
module.exports = async () => {
const port = process.env.PORT || 3333
const host = `http://localhost:${port}`
const server = createServer(port)
const { promise, resolve } = new function () {
this.promise = new Promise((resolve) => {
this.resolve = resolve
})
}
const virtualConsole = new jsdom.VirtualConsole();
virtualConsole.on('error', (...e) => { console.error(...e) })
const buildTime = function () {
var d = new Date(TIME);
console.log('build: ' + d.toLocaleDateString() + ' ' + d.toLocaleTimeString());
}
const dom = await JSDOM.fromURL(host, {
runScripts: 'dangerously',
resources: 'usable',
virtualConsole,
pretendToBeVisual: true,
beforeParse(window) {
window.fetch = window.fetch || ((url, option) => {
return fetch(host + url, option)
});
window.__prerender = resolve
}
})
await promise
const doc = dom.window.document
const injectScript = doc.createElement('script')
injectScript.textContent = [
`(${buildTime.toString().replace('TIME', Date.now()).replace(/\s{2,}/g, ' ')})()`
].join(';')
doc.head.appendChild(injectScript)
server.close()
const html = dom.serialize()
dom.window.close()
return html
}
if (require.main === module) {
console.log('Start prerendering...')
module.exports().then((renderedHtml) => {
console.log('Prerender done.', renderedHtml)
}).catch(e => {
console.error('prerender failed.', e)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment