Skip to content

Commit 71cb3ab

Browse files
Update ReactGrid sample to use newer server-side rendering APIs
1 parent 558aa31 commit 71cb3ab

File tree

9 files changed

+145
-96
lines changed

9 files changed

+145
-96
lines changed

samples/react/ReactGrid/.babelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
presets: ["es2015", "react"]
2+
"presets": ["es2015", "react"]
33
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3-
import createBrowserHistory from 'history/lib/createBrowserHistory';
4-
import ReactApp from './components/ReactApp.jsx';
3+
import { browserHistory } from 'react-router';
4+
import { ReactApp } from './components/ReactApp.jsx';
55
import 'bootstrap/dist/css/bootstrap.css';
66

77
// In the browser, we render into a DOM node and hook up to the browser's history APIs
8-
var history = createBrowserHistory();
9-
ReactDOM.render(<ReactApp history={ history } />, document.getElementById('react-app'));
8+
ReactDOM.render(<ReactApp history={ browserHistory } />, document.getElementById('react-app'));
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 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 './components/ReactApp';
6+
React;
7+
8+
export default function renderApp (params) {
9+
return new Promise((resolve, reject) => {
10+
// Match the incoming request against the list of client-side routes
11+
match({ routes, location: params.location }, (error, redirectLocation, renderProps) => {
12+
if (error) {
13+
throw error;
14+
}
15+
16+
// Build an instance of the application
17+
const history = createMemoryHistory(params.url);
18+
const app = <RouterContext {...renderProps} />;
19+
20+
// Render it as an HTML string which can be injected into the response
21+
const html = renderToString(app);
22+
resolve({ html });
23+
});
24+
});
25+
}

samples/react/ReactGrid/ReactApp/components/ReactApp.jsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ import { Router, Route } from 'react-router';
33
import { PeopleGrid } from './PeopleGrid.jsx';
44
import { PersonEditor } from './PersonEditor.jsx';
55

6-
export default class ReactApp extends React.Component {
6+
export const routes = <Route>
7+
<Route path="/" component={ PeopleGrid } />
8+
<Route path="/:pageIndex" component={ PeopleGrid } />
9+
<Route path="/edit/:personId" component={ PersonEditor } />
10+
</Route>;
11+
12+
export class ReactApp extends React.Component {
713
render() {
814
return (
9-
<Router history={this.props.history}>
10-
<Route path="/" component={PeopleGrid} />
11-
<Route path="/:pageIndex" component={PeopleGrid} />
12-
<Route path="/edit/:personId" component={PersonEditor} />
13-
</Router>
15+
<Router history={this.props.history} children={ routes } />
1416
);
1517
}
1618
}

samples/react/ReactGrid/Startup.cs

Lines changed: 77 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,77 @@
1-
using Microsoft.AspNet.Builder;
2-
using Microsoft.AspNet.Hosting;
3-
using Microsoft.AspNet.SpaServices;
4-
using Microsoft.Extensions.Configuration;
5-
using Microsoft.Extensions.DependencyInjection;
6-
using Microsoft.Extensions.Logging;
7-
using Microsoft.Extensions.PlatformAbstractions;
8-
9-
namespace ReactExample
10-
{
11-
public class Startup
12-
{
13-
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
14-
{
15-
// Setup configuration sources.
16-
var builder = new ConfigurationBuilder()
17-
.SetBasePath(appEnv.ApplicationBasePath)
18-
.AddJsonFile("appsettings.json")
19-
.AddEnvironmentVariables();
20-
Configuration = builder.Build();
21-
}
22-
23-
public IConfigurationRoot Configuration { get; set; }
24-
25-
// This method gets called by the runtime.
26-
public void ConfigureServices(IServiceCollection services)
27-
{
28-
// Add MVC services to the services container.
29-
services.AddMvc();
30-
}
31-
32-
// Configure is called after ConfigureServices is called.
33-
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
34-
{
35-
loggerFactory.MinimumLevel = LogLevel.Warning;
36-
loggerFactory.AddConsole();
37-
loggerFactory.AddDebug();
38-
39-
// Configure the HTTP request pipeline.
40-
41-
// Add the platform handler to the request pipeline.
42-
app.UseIISPlatformHandler();
43-
44-
// Add the following to the request pipeline only in development environment.
45-
if (env.IsDevelopment())
46-
{
47-
app.UseDeveloperExceptionPage();
48-
}
49-
else
50-
{
51-
// Add Error handling middleware which catches all application specific errors and
52-
// send the request to the following path or controller action.
53-
app.UseExceptionHandler("/Home/Error");
54-
}
55-
56-
// In dev mode, the JS/TS/etc is compiled and served dynamically and supports hot replacement.
57-
// In production, we assume you've used webpack to emit the prebuilt content to disk.
58-
if (env.IsDevelopment()) {
59-
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
60-
HotModuleReplacement = true,
61-
ReactHotModuleReplacement = true
62-
});
63-
}
64-
65-
// Add static files to the request pipeline.
66-
app.UseStaticFiles();
67-
68-
// Add MVC to the request pipeline.
69-
app.UseMvc(routes =>
70-
{
71-
routes.MapSpaFallbackRoute(
72-
name: "default",
73-
defaults: new { controller="Home", action = "Index" });
74-
});
75-
}
76-
}
77-
}
1+
using Microsoft.AspNet.Builder;
2+
using Microsoft.AspNet.Hosting;
3+
using Microsoft.AspNet.SpaServices.Webpack;
4+
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Logging;
7+
using Microsoft.Extensions.PlatformAbstractions;
8+
9+
namespace ReactExample
10+
{
11+
public class Startup
12+
{
13+
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
14+
{
15+
// Setup configuration sources.
16+
var builder = new ConfigurationBuilder()
17+
.SetBasePath(appEnv.ApplicationBasePath)
18+
.AddJsonFile("appsettings.json")
19+
.AddEnvironmentVariables();
20+
Configuration = builder.Build();
21+
}
22+
23+
public IConfigurationRoot Configuration { get; set; }
24+
25+
// This method gets called by the runtime.
26+
public void ConfigureServices(IServiceCollection services)
27+
{
28+
// Add MVC services to the services container.
29+
services.AddMvc();
30+
}
31+
32+
// Configure is called after ConfigureServices is called.
33+
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
34+
{
35+
loggerFactory.MinimumLevel = LogLevel.Warning;
36+
loggerFactory.AddConsole();
37+
loggerFactory.AddDebug();
38+
39+
// Configure the HTTP request pipeline.
40+
41+
// Add the platform handler to the request pipeline.
42+
app.UseIISPlatformHandler();
43+
44+
// Add the following to the request pipeline only in development environment.
45+
if (env.IsDevelopment())
46+
{
47+
app.UseDeveloperExceptionPage();
48+
}
49+
else
50+
{
51+
// Add Error handling middleware which catches all application specific errors and
52+
// send the request to the following path or controller action.
53+
app.UseExceptionHandler("/Home/Error");
54+
}
55+
56+
// In dev mode, the JS/TS/etc is compiled and served dynamically and supports hot replacement.
57+
// In production, we assume you've used webpack to emit the prebuilt content to disk.
58+
if (env.IsDevelopment()) {
59+
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
60+
HotModuleReplacement = true,
61+
ReactHotModuleReplacement = true
62+
});
63+
}
64+
65+
// Add static files to the request pipeline.
66+
app.UseStaticFiles();
67+
68+
// Add MVC to the request pipeline.
69+
app.UseMvc(routes =>
70+
{
71+
routes.MapSpaFallbackRoute(
72+
name: "default",
73+
defaults: new { controller="Home", action = "Index" });
74+
});
75+
}
76+
}
77+
}

samples/react/ReactGrid/Views/Home/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div id="react-app" asp-react-prerender-module="ReactApp/components/ReactApp.jsx"></div>
1+
<div id="react-app" asp-prerender-module="ReactApp/boot-server.jsx"></div>
22

33
@section scripts {
44
<script src="/dist/main.js"></script>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
@using ReactExample
22
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
3-
@addTagHelper "*, Microsoft.AspNet.ReactServices"
3+
@addTagHelper "*, Microsoft.AspNet.SpaServices"

samples/react/ReactGrid/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
"dependencies": {
55
"babel-core": "^6.4.5",
66
"bootstrap": "^3.3.5",
7+
"domain-task": "^1.0.0",
78
"formsy-react": "^0.17.0",
89
"formsy-react-components": "^0.6.3",
9-
"griddle-react": "^0.2.14",
10+
"griddle-react": "^0.3.1",
1011
"history": "^1.12.6",
11-
"react": "^0.14.0",
12-
"react-dom": "^0.14.0",
13-
"react-router": "^1.0.0-rc3",
12+
"react": "^0.14.7",
13+
"react-dom": "^0.14.7",
14+
"react-router": "^2.0.0-rc5",
1415
"underscore": "^1.8.3"
1516
},
1617
"devDependencies": {

src/Microsoft.AspNet.SpaServices/Content/Node/prerenderer.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,26 @@
88
// TODO: Consider some general method for checking if you have all the necessary NPM modules installed,
99
// and if not, giving an error that tells you what command to execute to install the missing ones.
1010
var fs = require('fs');
11-
var ts = require('ntypescript');
11+
var ts = requireIfInstalled('ntypescript');
1212
var babelCore = require('babel-core');
1313
var resolveBabelRc = require('babel-loader/lib/resolve-rc'); // If this ever breaks, we can easily scan up the directory hierarchy ourselves
1414
var origJsLoader = require.extensions['.js'];
1515

1616
function resolveBabelOptions(relativeToFilename) {
1717
var babelRcText = resolveBabelRc(relativeToFilename);
18-
return babelRcText ? JSON.parse(babelRcText) : {};
18+
try {
19+
return babelRcText ? JSON.parse(babelRcText) : {};
20+
} catch (ex) {
21+
ex.message = 'Error while parsing babelrc JSON: ' + ex.message;
22+
throw ex;
23+
}
1924
}
2025

2126
function loadViaTypeScript(module, filename) {
27+
if (!ts) {
28+
throw new Error('Can\'t load .ts/.tsx files because the \'ntypescript\' package isn\'t installed.\nModule requested: ' + module);
29+
}
30+
2231
// First perform a minimal transpilation from TS code to ES2015. This is very fast (doesn't involve type checking)
2332
// and is unlikely to need any special compiler options
2433
var src = fs.readFileSync(filename, 'utf8');
@@ -45,6 +54,19 @@ function loadViaBabel(module, filename) {
4554
}
4655
}
4756

57+
function requireIfInstalled(packageName) {
58+
return isPackageInstalled(packageName) ? require(packageName) : null;
59+
}
60+
61+
function isPackageInstalled(packageName) {
62+
try {
63+
require.resolve(packageName);
64+
return true;
65+
} catch(e) {
66+
return false;
67+
}
68+
}
69+
4870
function register() {
4971
require.extensions['.js'] = loadViaBabel;
5072
require.extensions['.jsx'] = loadViaBabel;

0 commit comments

Comments
 (0)