diff --git a/samples/react/ReactGrid/.babelrc b/samples/react/ReactGrid/.babelrc
index 15f26dd6be..d4e5f8d414 100644
--- a/samples/react/ReactGrid/.babelrc
+++ b/samples/react/ReactGrid/.babelrc
@@ -1,3 +1,3 @@
{
- presets: ["es2015", "react"]
+ "presets": ["es2015", "react"]
}
diff --git a/samples/react/ReactGrid/ReactApp/boot-client.jsx b/samples/react/ReactGrid/ReactApp/boot-client.jsx
index b50fcf30c9..d109cdf074 100644
--- a/samples/react/ReactGrid/ReactApp/boot-client.jsx
+++ b/samples/react/ReactGrid/ReactApp/boot-client.jsx
@@ -1,9 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import createBrowserHistory from 'history/lib/createBrowserHistory';
-import ReactApp from './components/ReactApp.jsx';
+import { browserHistory } from 'react-router';
+import { ReactApp } from './components/ReactApp.jsx';
import 'bootstrap/dist/css/bootstrap.css';
// In the browser, we render into a DOM node and hook up to the browser's history APIs
-var history = createBrowserHistory();
-ReactDOM.render(, document.getElementById('react-app'));
+ReactDOM.render(, document.getElementById('react-app'));
diff --git a/samples/react/ReactGrid/ReactApp/boot-server.jsx b/samples/react/ReactGrid/ReactApp/boot-server.jsx
new file mode 100644
index 0000000000..873802e26d
--- /dev/null
+++ b/samples/react/ReactGrid/ReactApp/boot-server.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { renderToString } from 'react-dom/server';
+import { match, RouterContext } from 'react-router';
+import createMemoryHistory from 'history/lib/createMemoryHistory';
+import { routes } from './components/ReactApp';
+React;
+
+export default function renderApp (params) {
+ return new Promise((resolve, reject) => {
+ // Match the incoming request against the list of client-side routes
+ match({ routes, location: params.location }, (error, redirectLocation, renderProps) => {
+ if (error) {
+ throw error;
+ }
+
+ // Build an instance of the application
+ const history = createMemoryHistory(params.url);
+ const app = ;
+
+ // Render it as an HTML string which can be injected into the response
+ const html = renderToString(app);
+ resolve({ html });
+ });
+ });
+}
diff --git a/samples/react/ReactGrid/ReactApp/components/ReactApp.jsx b/samples/react/ReactGrid/ReactApp/components/ReactApp.jsx
index 1efeef7d43..6978f1da57 100644
--- a/samples/react/ReactGrid/ReactApp/components/ReactApp.jsx
+++ b/samples/react/ReactGrid/ReactApp/components/ReactApp.jsx
@@ -3,14 +3,16 @@ import { Router, Route } from 'react-router';
import { PeopleGrid } from './PeopleGrid.jsx';
import { PersonEditor } from './PersonEditor.jsx';
-export default class ReactApp extends React.Component {
+export const routes =
+
+
+
+;
+
+export class ReactApp extends React.Component {
render() {
return (
-
-
-
-
-
+
);
}
}
diff --git a/samples/react/ReactGrid/Startup.cs b/samples/react/ReactGrid/Startup.cs
index eb55c5a5aa..6024c4269f 100755
--- a/samples/react/ReactGrid/Startup.cs
+++ b/samples/react/ReactGrid/Startup.cs
@@ -1,77 +1,77 @@
-using Microsoft.AspNet.Builder;
-using Microsoft.AspNet.Hosting;
-using Microsoft.AspNet.SpaServices;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.PlatformAbstractions;
-
-namespace ReactExample
-{
- public class Startup
- {
- public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
- {
- // Setup configuration sources.
- var builder = new ConfigurationBuilder()
- .SetBasePath(appEnv.ApplicationBasePath)
- .AddJsonFile("appsettings.json")
- .AddEnvironmentVariables();
- Configuration = builder.Build();
- }
-
- public IConfigurationRoot Configuration { get; set; }
-
- // This method gets called by the runtime.
- public void ConfigureServices(IServiceCollection services)
- {
- // Add MVC services to the services container.
- services.AddMvc();
- }
-
- // Configure is called after ConfigureServices is called.
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
- {
- loggerFactory.MinimumLevel = LogLevel.Warning;
- loggerFactory.AddConsole();
- loggerFactory.AddDebug();
-
- // Configure the HTTP request pipeline.
-
- // Add the platform handler to the request pipeline.
- app.UseIISPlatformHandler();
-
- // Add the following to the request pipeline only in development environment.
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- // Add Error handling middleware which catches all application specific errors and
- // send the request to the following path or controller action.
- app.UseExceptionHandler("/Home/Error");
- }
-
- // In dev mode, the JS/TS/etc is compiled and served dynamically and supports hot replacement.
- // In production, we assume you've used webpack to emit the prebuilt content to disk.
- if (env.IsDevelopment()) {
- app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
- HotModuleReplacement = true,
- ReactHotModuleReplacement = true
- });
- }
-
- // Add static files to the request pipeline.
- app.UseStaticFiles();
-
- // Add MVC to the request pipeline.
- app.UseMvc(routes =>
- {
- routes.MapSpaFallbackRoute(
- name: "default",
- defaults: new { controller="Home", action = "Index" });
- });
- }
- }
-}
+using Microsoft.AspNet.Builder;
+using Microsoft.AspNet.Hosting;
+using Microsoft.AspNet.SpaServices.Webpack;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.PlatformAbstractions;
+
+namespace ReactExample
+{
+ public class Startup
+ {
+ public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
+ {
+ // Setup configuration sources.
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(appEnv.ApplicationBasePath)
+ .AddJsonFile("appsettings.json")
+ .AddEnvironmentVariables();
+ Configuration = builder.Build();
+ }
+
+ public IConfigurationRoot Configuration { get; set; }
+
+ // This method gets called by the runtime.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ // Add MVC services to the services container.
+ services.AddMvc();
+ }
+
+ // Configure is called after ConfigureServices is called.
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ {
+ loggerFactory.MinimumLevel = LogLevel.Warning;
+ loggerFactory.AddConsole();
+ loggerFactory.AddDebug();
+
+ // Configure the HTTP request pipeline.
+
+ // Add the platform handler to the request pipeline.
+ app.UseIISPlatformHandler();
+
+ // Add the following to the request pipeline only in development environment.
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+ else
+ {
+ // Add Error handling middleware which catches all application specific errors and
+ // send the request to the following path or controller action.
+ app.UseExceptionHandler("/Home/Error");
+ }
+
+ // In dev mode, the JS/TS/etc is compiled and served dynamically and supports hot replacement.
+ // In production, we assume you've used webpack to emit the prebuilt content to disk.
+ if (env.IsDevelopment()) {
+ app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
+ HotModuleReplacement = true,
+ ReactHotModuleReplacement = true
+ });
+ }
+
+ // Add static files to the request pipeline.
+ app.UseStaticFiles();
+
+ // Add MVC to the request pipeline.
+ app.UseMvc(routes =>
+ {
+ routes.MapSpaFallbackRoute(
+ name: "default",
+ defaults: new { controller="Home", action = "Index" });
+ });
+ }
+ }
+}
diff --git a/samples/react/ReactGrid/Views/Home/Index.cshtml b/samples/react/ReactGrid/Views/Home/Index.cshtml
index 40b1291538..d16c1640c1 100755
--- a/samples/react/ReactGrid/Views/Home/Index.cshtml
+++ b/samples/react/ReactGrid/Views/Home/Index.cshtml
@@ -1,4 +1,4 @@
-
+
@section scripts {
diff --git a/samples/react/ReactGrid/Views/_ViewImports.cshtml b/samples/react/ReactGrid/Views/_ViewImports.cshtml
index 5fb314717b..5746f7ee71 100755
--- a/samples/react/ReactGrid/Views/_ViewImports.cshtml
+++ b/samples/react/ReactGrid/Views/_ViewImports.cshtml
@@ -1,3 +1,3 @@
@using ReactExample
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
-@addTagHelper "*, Microsoft.AspNet.ReactServices"
+@addTagHelper "*, Microsoft.AspNet.SpaServices"
diff --git a/samples/react/ReactGrid/package.json b/samples/react/ReactGrid/package.json
index 826c5a57bf..57d8ac4f60 100644
--- a/samples/react/ReactGrid/package.json
+++ b/samples/react/ReactGrid/package.json
@@ -4,13 +4,14 @@
"dependencies": {
"babel-core": "^6.4.5",
"bootstrap": "^3.3.5",
+ "domain-task": "^1.0.0",
"formsy-react": "^0.17.0",
"formsy-react-components": "^0.6.3",
- "griddle-react": "^0.2.14",
+ "griddle-react": "^0.3.1",
"history": "^1.12.6",
- "react": "^0.14.0",
- "react-dom": "^0.14.0",
- "react-router": "^1.0.0-rc3",
+ "react": "^0.14.7",
+ "react-dom": "^0.14.7",
+ "react-router": "^2.0.0-rc5",
"underscore": "^1.8.3"
},
"devDependencies": {
diff --git a/src/Microsoft.AspNet.SpaServices/Content/Node/prerenderer.js b/src/Microsoft.AspNet.SpaServices/Content/Node/prerenderer.js
index 23644a0d1f..e44894144e 100644
--- a/src/Microsoft.AspNet.SpaServices/Content/Node/prerenderer.js
+++ b/src/Microsoft.AspNet.SpaServices/Content/Node/prerenderer.js
@@ -8,17 +8,26 @@
// TODO: Consider some general method for checking if you have all the necessary NPM modules installed,
// and if not, giving an error that tells you what command to execute to install the missing ones.
var fs = require('fs');
-var ts = require('ntypescript');
+var ts = requireIfInstalled('ntypescript');
var babelCore = require('babel-core');
var resolveBabelRc = require('babel-loader/lib/resolve-rc'); // If this ever breaks, we can easily scan up the directory hierarchy ourselves
var origJsLoader = require.extensions['.js'];
function resolveBabelOptions(relativeToFilename) {
var babelRcText = resolveBabelRc(relativeToFilename);
- return babelRcText ? JSON.parse(babelRcText) : {};
+ try {
+ return babelRcText ? JSON.parse(babelRcText) : {};
+ } catch (ex) {
+ ex.message = 'Error while parsing babelrc JSON: ' + ex.message;
+ throw ex;
+ }
}
function loadViaTypeScript(module, filename) {
+ if (!ts) {
+ throw new Error('Can\'t load .ts/.tsx files because the \'ntypescript\' package isn\'t installed.\nModule requested: ' + module);
+ }
+
// First perform a minimal transpilation from TS code to ES2015. This is very fast (doesn't involve type checking)
// and is unlikely to need any special compiler options
var src = fs.readFileSync(filename, 'utf8');
@@ -45,6 +54,19 @@ function loadViaBabel(module, filename) {
}
}
+function requireIfInstalled(packageName) {
+ return isPackageInstalled(packageName) ? require(packageName) : null;
+}
+
+function isPackageInstalled(packageName) {
+ try {
+ require.resolve(packageName);
+ return true;
+ } catch(e) {
+ return false;
+ }
+}
+
function register() {
require.extensions['.js'] = loadViaBabel;
require.extensions['.jsx'] = loadViaBabel;