1 | import React from "react"
|
2 | import { renderToStaticMarkup } from "react-dom/server"
|
3 | import { merge } from "lodash"
|
4 | import apiRunner from "./api-runner-ssr"
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | const testRequireError = (moduleName, err) => {
|
10 | const regex = new RegExp(`Error: Cannot find module\\s.${moduleName}`)
|
11 | const firstLine = err.toString().split(`\n`)[0]
|
12 | return regex.test(firstLine)
|
13 | }
|
14 |
|
15 | let Html
|
16 | try {
|
17 | Html = require(`../src/html`)
|
18 | } catch (err) {
|
19 | if (testRequireError(`../src/html`, err)) {
|
20 | Html = require(`./default-html`)
|
21 | } else {
|
22 | console.log(`There was an error requiring "src/html.js"\n\n`, err, `\n\n`)
|
23 | process.exit()
|
24 | }
|
25 | }
|
26 |
|
27 | Html = Html && Html.__esModule ? Html.default : Html
|
28 |
|
29 | export default (pagePath, callback) => {
|
30 | let headComponents = []
|
31 | let htmlAttributes = {}
|
32 | let bodyAttributes = {}
|
33 | let preBodyComponents = []
|
34 | let postBodyComponents = []
|
35 | let bodyProps = {}
|
36 | let htmlStr
|
37 |
|
38 | const setHeadComponents = components => {
|
39 | headComponents = headComponents.concat(components)
|
40 | }
|
41 |
|
42 | const setHtmlAttributes = attributes => {
|
43 | htmlAttributes = merge(htmlAttributes, attributes)
|
44 | }
|
45 |
|
46 | const setBodyAttributes = attributes => {
|
47 | bodyAttributes = merge(bodyAttributes, attributes)
|
48 | }
|
49 |
|
50 | const setPreBodyComponents = components => {
|
51 | preBodyComponents = preBodyComponents.concat(components)
|
52 | }
|
53 |
|
54 | const setPostBodyComponents = components => {
|
55 | postBodyComponents = postBodyComponents.concat(components)
|
56 | }
|
57 |
|
58 | const setBodyProps = props => {
|
59 | bodyProps = merge({}, bodyProps, props)
|
60 | }
|
61 |
|
62 | const getHeadComponents = () => headComponents
|
63 |
|
64 | const replaceHeadComponents = components => {
|
65 | headComponents = components
|
66 | }
|
67 |
|
68 | const getPreBodyComponents = () => preBodyComponents
|
69 |
|
70 | const replacePreBodyComponents = components => {
|
71 | preBodyComponents = components
|
72 | }
|
73 |
|
74 | const getPostBodyComponents = () => postBodyComponents
|
75 |
|
76 | const replacePostBodyComponents = components => {
|
77 | postBodyComponents = components
|
78 | }
|
79 |
|
80 | apiRunner(`onRenderBody`, {
|
81 | setHeadComponents,
|
82 | setHtmlAttributes,
|
83 | setBodyAttributes,
|
84 | setPreBodyComponents,
|
85 | setPostBodyComponents,
|
86 | setBodyProps,
|
87 | pathname: pagePath,
|
88 | })
|
89 |
|
90 | apiRunner(`onPreRenderHTML`, {
|
91 | getHeadComponents,
|
92 | replaceHeadComponents,
|
93 | getPreBodyComponents,
|
94 | replacePreBodyComponents,
|
95 | getPostBodyComponents,
|
96 | replacePostBodyComponents,
|
97 | pathname: pagePath,
|
98 | })
|
99 |
|
100 | const htmlElement = React.createElement(Html, {
|
101 | ...bodyProps,
|
102 | body: ``,
|
103 | headComponents: headComponents.concat([
|
104 | <script key={`io`} src="/socket.io/socket.io.js" />,
|
105 | ]),
|
106 | htmlAttributes,
|
107 | bodyAttributes,
|
108 | preBodyComponents,
|
109 | postBodyComponents: postBodyComponents.concat([
|
110 | <script key={`commons`} src="/commons.js" />,
|
111 | ]),
|
112 | })
|
113 | htmlStr = renderToStaticMarkup(htmlElement)
|
114 | htmlStr = `<!DOCTYPE html>${htmlStr}`
|
115 |
|
116 | callback(null, htmlStr)
|
117 | }
|