|
@@ -2,17 +2,67 @@ var express = require('express');
|
|
|
var path = require('path');
|
|
|
var compression = require('compression');
|
|
|
|
|
|
+import React from 'react';
|
|
|
+import { renderToString } from 'react-dom/server';
|
|
|
+import { match, RouterContext } from 'react-router';
|
|
|
+import routes from './modules/routes';
|
|
|
+
|
|
|
var app = express();
|
|
|
+
|
|
|
app.use(compression());
|
|
|
|
|
|
-// Server our static stuff like index.css
|
|
|
+// serve our static stuff like index.css
|
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
|
|
|
|
// Send all requests to index.html so browserHistory in React Router works
|
|
|
-app.get('*', function (req, res) {
|
|
|
- res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
|
|
+app.get('*', (req, res) => {
|
|
|
+ match({ routes, location: req.url }, (err, redirect, props) => {
|
|
|
+ console.log(`SSR for ${req.url}`);
|
|
|
+ // in here we can make some decisions all at once
|
|
|
+ if (err) {
|
|
|
+ // there was an error somewhere during route matching
|
|
|
+ res.status(500).send(err.message);
|
|
|
+ } else if (redirect) {
|
|
|
+ // we haven't talked about `onEnter` hooks on routes, but before a
|
|
|
+ // route is entered, it can redirect. Here we handle on the server.
|
|
|
+ res.redirect(redirect.pathname + redirect.search);
|
|
|
+ } else if (props) {
|
|
|
+ // if we got props then we matched a route and can render
|
|
|
+
|
|
|
+ // `RouterContext is what the `Router` renders. `Router` keeps these `props`
|
|
|
+ // in its state as it listens to `browserHistory`. But on the server, our
|
|
|
+ // app is stateless, so we need to use `match` to get these props before
|
|
|
+ // rendering.
|
|
|
+ const appHtml = renderToString(<RouterContext { ...props } />);
|
|
|
+
|
|
|
+ // Dump the HTML into a template, lots of ways to do this, but none are
|
|
|
+ // really influenced by React Router, so we're just using a little function,
|
|
|
+ // `renderPage`.
|
|
|
+ res.send(renderPage(appHtml));
|
|
|
+ } else {
|
|
|
+ // no errors, no redirect, we just didn't match anything
|
|
|
+ res.status(404).send("Not found");
|
|
|
+ }
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
+function renderPage(appHtml) {
|
|
|
+ return `
|
|
|
+ <!DOCTYPE HTML>
|
|
|
+ <html>
|
|
|
+ <head>
|
|
|
+ <meta charset="utf-8" />
|
|
|
+ <title>My first React Router App</title>
|
|
|
+ <link rel="stylesheet" href="/index.css" />
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <div id="app">${appHtml}</div>
|
|
|
+ <script src="/bundle.js"></script>
|
|
|
+ </body>
|
|
|
+ </html>
|
|
|
+ `;
|
|
|
+}
|
|
|
+
|
|
|
var PORT = process.env.PORT || 8080;
|
|
|
app.listen(PORT, function () {
|
|
|
console.log('"Production" Express server running at localhost:' + PORT);
|