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 | <meta key="environment" name="note" content="environment=development" />,
|
32 | ]
|
33 | let htmlAttributes = {}
|
34 | let bodyAttributes = {}
|
35 | let preBodyComponents = []
|
36 | let postBodyComponents = []
|
37 | let bodyProps = {}
|
38 | let htmlStr
|
39 |
|
40 | const setHeadComponents = components => {
|
41 | headComponents = headComponents.concat(components)
|
42 | }
|
43 |
|
44 | const setHtmlAttributes = attributes => {
|
45 | htmlAttributes = merge(htmlAttributes, attributes)
|
46 | }
|
47 |
|
48 | const setBodyAttributes = attributes => {
|
49 | bodyAttributes = merge(bodyAttributes, attributes)
|
50 | }
|
51 |
|
52 | const setPreBodyComponents = components => {
|
53 | preBodyComponents = preBodyComponents.concat(components)
|
54 | }
|
55 |
|
56 | const setPostBodyComponents = components => {
|
57 | postBodyComponents = postBodyComponents.concat(components)
|
58 | }
|
59 |
|
60 | const setBodyProps = props => {
|
61 | bodyProps = merge({}, bodyProps, props)
|
62 | }
|
63 |
|
64 | const getHeadComponents = () => headComponents
|
65 |
|
66 | const replaceHeadComponents = components => {
|
67 | headComponents = components
|
68 | }
|
69 |
|
70 | const getPreBodyComponents = () => preBodyComponents
|
71 |
|
72 | const replacePreBodyComponents = components => {
|
73 | preBodyComponents = components
|
74 | }
|
75 |
|
76 | const getPostBodyComponents = () => postBodyComponents
|
77 |
|
78 | const replacePostBodyComponents = components => {
|
79 | postBodyComponents = components
|
80 | }
|
81 |
|
82 | apiRunner(`onRenderBody`, {
|
83 | setHeadComponents,
|
84 | setHtmlAttributes,
|
85 | setBodyAttributes,
|
86 | setPreBodyComponents,
|
87 | setPostBodyComponents,
|
88 | setBodyProps,
|
89 | pathname: pagePath,
|
90 | })
|
91 |
|
92 | apiRunner(`onPreRenderHTML`, {
|
93 | getHeadComponents,
|
94 | replaceHeadComponents,
|
95 | getPreBodyComponents,
|
96 | replacePreBodyComponents,
|
97 | getPostBodyComponents,
|
98 | replacePostBodyComponents,
|
99 | pathname: pagePath,
|
100 | })
|
101 |
|
102 | const htmlElement = React.createElement(Html, {
|
103 | ...bodyProps,
|
104 | body: ``,
|
105 | headComponents: headComponents.concat([
|
106 | <script key={`io`} src="/socket.io/socket.io.js" />,
|
107 | ]),
|
108 | htmlAttributes,
|
109 | bodyAttributes,
|
110 | preBodyComponents,
|
111 | postBodyComponents: postBodyComponents.concat([
|
112 | <script key={`commons`} src="/commons.js" />,
|
113 | ]),
|
114 | })
|
115 | htmlStr = renderToStaticMarkup(htmlElement)
|
116 | htmlStr = `<!DOCTYPE html>${htmlStr}`
|
117 |
|
118 | callback(null, htmlStr)
|
119 | }
|