@@ -2,18 +2,18 @@ import fs from 'fs';
2
2
import Express from 'express' ;
3
3
import helmet from 'helmet' ;
4
4
import path from 'path' ;
5
- import serialize from 'serialize-javascript' ;
6
5
import cookie from 'react-cookie' ;
7
6
import React from 'react' ;
7
+ import ReactDOM from 'react-dom/server' ;
8
+ import ReactHelmet from 'react-helmet' ;
8
9
9
- import { stripIndent } from 'common-tags' ;
10
- import { renderToString } from 'react-dom/server' ;
11
10
import { Provider } from 'react-redux' ;
12
11
import { match } from 'react-router' ;
13
12
import { ReduxAsyncConnect , loadOnServer } from 'redux-async-connect' ;
14
13
15
14
import WebpackIsomorphicTools from 'webpack-isomorphic-tools' ;
16
15
import WebpackIsomorphicToolsConfig from 'webpack-isomorphic-tools-config' ;
16
+ import ServerHtml from 'core/containers/ServerHtml' ;
17
17
18
18
import config from 'config' ;
19
19
import { setJWT } from 'core/actions' ;
@@ -29,7 +29,7 @@ global.CLIENT = false;
29
29
global . SERVER = true ;
30
30
global . DEVELOPMENT = env === 'development' ;
31
31
32
- export default function ( routes , createStore ) {
32
+ function baseServer ( routes , createStore , { appInstanceName = appName } = { } ) {
33
33
const app = new Express ( ) ;
34
34
app . disable ( 'x-powered-by' ) ;
35
35
@@ -58,7 +58,7 @@ export default function(routes, createStore) {
58
58
app . post ( '/__cspreport__' , ( req , res ) => res . status ( 200 ) . end ( 'ok' ) ) ;
59
59
60
60
// Redirect from / for the search app it's a 302 to prevent caching.
61
- if ( appName === 'search' ) {
61
+ if ( appInstanceName === 'search' ) {
62
62
app . get ( '/' , ( req , res ) => res . redirect ( 302 , '/search' ) ) ;
63
63
}
64
64
@@ -82,67 +82,37 @@ export default function(routes, createStore) {
82
82
store . dispatch ( setJWT ( token ) ) ;
83
83
}
84
84
85
- return loadOnServer ( { ...renderProps , store} ) . then ( ( ) => {
86
- const InitialComponent = (
87
- < Provider store = { store } key = "provider" >
88
- < ReduxAsyncConnect { ...renderProps } />
89
- </ Provider >
90
- ) ;
91
-
92
- const componentHTML = renderToString ( InitialComponent ) ;
93
-
94
- const assets = webpackIsomorphicTools . assets ( ) ;
95
-
96
- // Get SRI for deployed services only.
97
- const sri = isDeployed ? JSON . parse (
98
- fs . readFileSync ( path . join ( config . get ( 'basePath' ) , 'dist/sri.json' ) )
99
- ) : { } ;
100
-
101
- const styles = Object . keys ( assets . styles ) . map ( ( style ) => {
102
- const cssHash = sri [ path . basename ( assets . styles [ style ] ) ] ;
103
- if ( isDeployed && ! cssHash ) {
104
- throw new Error ( 'Missing SRI Data' ) ;
105
- }
106
- const cssSRI = sri && cssHash ? ` integrity="${ cssHash } " crossorigin="anonymous"` : '' ;
107
- return `<link href="${ assets . styles [ style ] } "${ cssSRI }
108
- rel="stylesheet" type="text/css" />` ;
109
- } ) . join ( '\n' ) ;
110
-
111
- const script = Object . keys ( assets . javascript ) . map ( ( js ) => {
112
- const jsHash = sri [ path . basename ( assets . javascript [ js ] ) ] ;
113
- if ( isDeployed && ! jsHash ) {
114
- throw new Error ( 'Missing SRI Data' ) ;
115
- }
116
- const jsSRI = sri && jsHash ? ` integrity="${ jsHash } " crossorigin="anonymous"` : '' ;
117
- return `<script src="${ assets . javascript [ js ] } "${ jsSRI } ></script>` ;
118
- } ) . join ( '\n' ) ;
119
-
120
- const HTML = stripIndent `
121
- <!DOCTYPE html>
122
- <html>
123
- <head>
124
- <meta charset="utf-8">
125
- <title>Isomorphic Redux Demo</title>
126
- <meta name="viewport" content="width=device-width, initial-scale=1" />
127
- ${ styles }
128
- </head>
129
- <body>
130
- <div id="react-view">${ componentHTML } </div>
131
- <script type="application/json" id="redux-store-state">
132
- ${ serialize ( store . getState ( ) ) }
133
- </script>
134
- ${ script }
135
- </body>
136
- </html>` ;
137
-
138
- res . header ( 'Content-Type' , 'text/html' ) ;
139
- return res . end ( HTML ) ;
140
- } )
141
- . catch ( ( error ) => {
142
- // eslint-disable-next-line no-console
143
- console . error ( error . stack ) ;
144
- res . status ( 500 ) . end ( errorString ) ;
145
- } ) ;
85
+ return loadOnServer ( { ...renderProps , store} )
86
+ . then ( ( ) => {
87
+ const InitialComponent = (
88
+ < Provider store = { store } key = "provider" >
89
+ < ReduxAsyncConnect { ...renderProps } />
90
+ </ Provider >
91
+ ) ;
92
+
93
+ // Get SRI for deployed services only.
94
+ const sriData = ( isDeployed ) ? JSON . parse (
95
+ fs . readFileSync ( path . join ( config . get ( 'basePath' ) , 'dist/sri.json' ) )
96
+ ) : { } ;
97
+
98
+ const pageProps = {
99
+ appName : appInstanceName ,
100
+ assets : webpackIsomorphicTools . assets ( ) ,
101
+ component : InitialComponent ,
102
+ head : ReactHelmet . rewind ( ) ,
103
+ env,
104
+ sriData,
105
+ store,
106
+ } ;
107
+
108
+ const HTML = ReactDOM . renderToString ( < ServerHtml { ...pageProps } /> ) ;
109
+ res . send ( `<!DOCTYPE html>${ HTML } ` ) ;
110
+ } )
111
+ . catch ( ( error ) => {
112
+ // eslint-disable-next-line no-console
113
+ console . error ( error . stack ) ;
114
+ res . status ( 500 ) . end ( errorString ) ;
115
+ } ) ;
146
116
} ) ;
147
117
} ) ;
148
118
@@ -174,7 +144,9 @@ export function runServer({listen = true, app = appName} = {}) {
174
144
// Webpack Isomorphic tools is ready
175
145
// now fire up the actual server.
176
146
return new Promise ( ( resolve , reject ) => {
177
- const server = require ( `${ app } /server` ) . default ;
147
+ const routes = require ( `${ app } /routes` ) . default ;
148
+ const createStore = require ( `${ app } /store` ) . default ;
149
+ const server = baseServer ( routes , createStore , { appInstanceName : app } ) ;
178
150
if ( listen === true ) {
179
151
server . listen ( port , host , ( err ) => {
180
152
if ( err ) {
@@ -196,3 +168,5 @@ export function runServer({listen = true, app = appName} = {}) {
196
168
console . error ( err ) ;
197
169
} ) ;
198
170
}
171
+
172
+ export default baseServer ;
0 commit comments