Skip to content

Commit eac7668

Browse files
Enable server-side rendering for ReactSpa template
1 parent f0b0160 commit eac7668

File tree

6 files changed

+41
-2
lines changed

6 files changed

+41
-2
lines changed

templates/ReactSpa/ClientApp/boot.tsx renamed to templates/ReactSpa/ClientApp/boot-client.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import * as ReactDOM from 'react-dom';
66
import { browserHistory, Router } from 'react-router';
77
import { routes } from './routes';
88

9+
// This code starts up the React app when it runs in a browser. It sets up the routing configuration
10+
// and injects the app into a DOM element.
911
ReactDOM.render(
1012
<Router history={ browserHistory } children={ routes } />,
1113
document.getElementById('react-app')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import * as React from 'react';
2+
import { renderToString } from 'react-dom/server';
3+
import { match, RouterContext } from 'react-router';
4+
import createMemoryHistory from 'history/lib/createMemoryHistory';
5+
import { routes } from './routes';
6+
7+
// The 'asp-prerender-module' tag helper invokes the following function when the React app is to
8+
// be prerendered on the server. It runs asynchronously, and issues a callback with the React app's
9+
// initial HTML and any other state variables.
10+
11+
export default function (params: any): Promise<{ html: string }> {
12+
return new Promise<{ html: string, globals: { [key: string]: any } }>((resolve, reject) => {
13+
// Match the incoming request against the list of client-side routes, and reject if there was no match
14+
match({ routes, location: params.location }, (error, redirectLocation, renderProps: any) => {
15+
if (error) {
16+
throw error;
17+
}
18+
19+
// Build an instance of the application and perform an initial render.
20+
// This will cause any async tasks (e.g., data access) to begin.
21+
const history = createMemoryHistory(params.url);
22+
const app = <RouterContext {...renderProps} />;
23+
renderToString(app);
24+
25+
// Once the tasks are done, we can perform the final render
26+
params.domainTasks.then(() => {
27+
resolve({
28+
html: renderToString(app),
29+
globals: { /* Supply any other JSON-serializable data you want to make available on the client */ }
30+
});
31+
}, reject); // Also propagate any errors back into the host application
32+
});
33+
});
34+
}

templates/ReactSpa/Views/Home/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
ViewData["Title"] = "Home Page";
33
}
44

5-
<div id="react-app">Loading...</div>
5+
<div id="react-app" asp-prerender-module="ClientApp/boot-server">Loading...</div>
66

77
@section scripts {
88
<script src="~/dist/main.js" asp-append-version="true"></script>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
@using WebApplicationBasic
22
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
3+
@addTagHelper "*, Microsoft.AspNet.SpaServices"

templates/ReactSpa/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"extract-text-webpack-plugin": "^1.0.1",
1414
"file-loader": "^0.8.5",
1515
"jquery": "^2.2.1",
16+
"ntypescript": "^1.201602232306.1",
1617
"react-transform-hmr": "^1.0.2",
1718
"style-loader": "^0.13.0",
1819
"ts-loader": "^0.8.1",
@@ -24,6 +25,7 @@
2425
},
2526
"dependencies": {
2627
"babel-core": "^6.5.2",
28+
"domain-task": "^1.0.0",
2729
"react": "^0.14.7",
2830
"react-dom": "^0.14.7",
2931
"react-router": "^2.0.0"

templates/ReactSpa/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module.exports = merge({
1717
]
1818
},
1919
entry: {
20-
main: ['./ClientApp/boot.tsx'],
20+
main: ['./ClientApp/boot-client.tsx'],
2121
vendor: ['bootstrap', 'bootstrap/dist/css/bootstrap.css', 'style-loader', 'jquery']
2222
},
2323
output: {

0 commit comments

Comments
 (0)