This repository has been archived by the owner on Oct 28, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
78 lines (65 loc) · 2.02 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Ignore assets in SSR
import * as R from "@paqmind/ramda"
import Express from "express"
import {fromDOMEvent} from "framework"
import ignoreAssets from "ignore-styles"
import K from "kefir"
import React from "react"
import ReactDOMServer from "react-dom/server"
import {layout200} from "./layout"
// CLIENT
// Note: simplified; good SSR happens in a separate process and never crashes the main server
import app, {seed} from "client/root"
import {appKey} from "client/meta"
//
ignoreAssets([".less", ".css", ".jpg", ".jpeg", ".png", ".gif", ".svg"])
let router = Express.Router()
let timeoutError = (delayMs) =>
K.later(delayMs, K.constantError(new Error("timeout"))).flatMap()
let hasLoadingApps = (state) =>
R.any(Boolean, R.values(state._loading))
let toProperty = (x) => x.toProperty().skipDuplicates(R.equals)
router.get("/*", (req, res, next) => {
/*if (req.query.noAPP) { TODO special layout, useful for debugging as SSR can be a PITA to test
res.send(layout200cut({
appKey,
appHTML: "",
state: {},
project,
}))
} else*/ if (req.query.noSSR) {
res.send(layout200({
appKey,
appHTML: "",
state: R.merge(seed, {url: req.originalUrl}),
}))
} else {
let sources = {
state$: K.pool(),
DOM: fromDOMEvent("#" + appKey),
}
let sinks = app(
R.over2("state$", toProperty, sources),
appKey
)
sources.state$.plug(K.constant(R.merge(seed, {url: req.originalUrl})))
let finalState$ = sinks.state$
.throttle(10)
.skipDuplicates(R.equals) // TODO recheck this line
.skipWhile(hasLoadingApps)
.merge(timeoutError(500))
.take(1)
.takeErrors(1)
.toProperty()
sinks.state$.takeUntilBy(finalState$).observe(state => {
setImmediate(() => {
sources.state$.plug(K.constant(state))
})
})
finalState$.observe(state => {
let appHTML = ReactDOMServer.renderToString(<sinks.Component/>)
res.send(layout200({appKey, appHTML, state}))
}, next)
}
})
export default router