UNPKG

3.12 kBJavaScriptView Raw
1import React from "react"
2import { renderToStaticMarkup } from "react-dom/server"
3import { merge } from "lodash"
4import apiRunner from "./api-runner-ssr"
5// import testRequireError from "./test-require-error"
6// For some extremely mysterious reason, webpack adds the above module *after*
7// this module so that when this code runs, testRequireError is undefined.
8// So in the meantime, we'll just inline it.
9const 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
15let Html
16try {
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
27Html = Html && Html.__esModule ? Html.default : Html
28
29export 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}