@platform/react.ssr
Version:
An SSR (server-side-render) system for react apps bundled with ParcelJS and hosted on S3.
76 lines (75 loc) • 2.37 kB
JavaScript
import { http, util, pathToRegex, cheerio } from '../common';
export class Route {
constructor(args) {
this.site = args.site;
this.def = args.route;
}
static format(args) {
const { input } = args;
if (typeof input !== 'object') {
return undefined;
}
const entry = util.asString(input.entry);
const paths = Array.isArray(input.path) ? input.path : [input.path];
const path = paths.filter(path => Boolean(path) && typeof path === 'string');
return { entry, path };
}
get paths() {
return this.def.path;
}
get version() {
return util.firstSemver(this.site.bundle) || '0.0.0';
}
get bundleUrl() {
const base = util.stripSlashes(this.site.baseUrl);
const path = util.stripSlashes(this.site.bundle);
return `${base}/${path}`;
}
async entry(args = {}) {
if (this._entry && !args.force) {
return this._entry;
}
const filename = this.def.entry;
const url = `${this.bundleUrl}/${filename}`;
const res = await http.get(url);
let status = 200;
if (!res.ok) {
status = res.status;
}
let html = res.ok ? res.body : '';
const version = this.version;
html = this.formatHtml({ html, filename, version });
const ok = status.toString().startsWith('2');
const entry = {
ok,
status,
url,
html,
};
this._entry = entry;
return entry;
}
isMatch(path) {
if (!this._regexps) {
this._regexps = this.paths.map(pattern => pathToRegex(pattern));
}
return this._regexps.some(regex => Boolean(regex.exec(path)));
}
toObject() {
return Object.assign({}, this.def);
}
formatHtml(args) {
const { filename, html, version } = args;
const entry = this.site.entries.find(item => item.file === filename);
if (!html || !entry) {
return html;
}
const $ = cheerio.load(html);
const root = $(`div#${entry.id}`);
root.attr('data-version', version);
root.html(entry.html);
$('head').append(`<style>${entry.css}</style>`);
return $.html();
}
}
Route.create = (args) => new Route(args);