diff --git a/lib/utils/extract.js b/lib/utils/extract.js index 5d931c0..0638b8e 100644 --- a/lib/utils/extract.js +++ b/lib/utils/extract.js @@ -2,12 +2,13 @@ const sander = require('sander'); const app = require('express')(); const cheerio = require('cheerio'); const fetch = require('node-fetch'); +const { URL } = require('url'); const sapper = require('../index.js'); const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; const { dest } = require('../config.js'); -const prefix = `http://localhost:${PORT}`; +const origin = `http://localhost:${PORT}`; module.exports = function() { // Prep output directory @@ -18,16 +19,29 @@ module.exports = function() { sander.copyFileSync(`${dest}/service-worker.js`).to(`${OUTPUT_DIR}/service-worker.js`); // Intercept server route fetches + function save(res) { + res = res.clone(); + + return res.text().then(body => { + const { pathname } = new URL(res.url); + let dest = OUTPUT_DIR + pathname; + + const type = res.headers.get('Content-Type'); + if (type.startsWith('text/html;')) dest += '/index.html'; + + sander.writeFileSync(dest, body); + + return body; + }); + } + global.fetch = (url, opts) => { if (url[0] === '/') { - const dest = OUTPUT_DIR + url; url = `http://localhost:${PORT}${url}`; return fetch(url, opts) .then(r => { - r.clone().text().then(body => { - sander.writeFileSync(dest, body); - }); + save(r); return r; }); } @@ -40,18 +54,18 @@ module.exports = function() { const seen = new Set(); - function handle(pathname) { - if (pathname[0] !== '/') return; + function handle(url) { + if (url.origin !== origin) return; - if (seen.has(pathname)) return; - seen.add(pathname); + if (seen.has(url.pathname)) return; + seen.add(url.pathname); - return fetch(`${prefix}${pathname}`) - .then(r => r.text()) + return fetch(url.href) + .then(r => { + save(r); + return r.text(); + }) .then(body => { - const dest = OUTPUT_DIR + pathname + '/index.html'; - sander.writeFileSync(dest, body); - const $ = cheerio.load(body); const hrefs = []; @@ -59,13 +73,15 @@ module.exports = function() { hrefs.push($a.attribs.href); }); - return hrefs.reduce((promise, href) => promise.then(() => handle(href)), Promise.resolve()); + return hrefs.reduce((promise, href) => { + return promise.then(() => handle(new URL(href, url.href))); + }, Promise.resolve()); }) .catch(err => { - console.error(`Error rendering ${pathname}: ${err.message}`); + console.error(`Error rendering ${url.pathname}: ${err.message}`); }); } - return handle('/') // TODO all static routes + return handle(new URL(origin)) // TODO all static routes .then(() => server.close()); };