Enable server-side prerendering in React+Redux template

This commit is contained in:
SteveSandersonMS
2016-03-07 15:11:13 +00:00
parent cf7a519919
commit c44ceebc12
10 changed files with 54 additions and 22 deletions

View File

@@ -0,0 +1,38 @@
import * as React from 'react';
import { Provider } from 'react-redux';
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import createMemoryHistory from 'history/lib/createMemoryHistory';
import routes from './routes';
import configureStore from './configureStore';
export default function (params: any): Promise<{ html: string }> {
return new Promise<{ html: string, globals: { [key: string]: any } }>((resolve, reject) => {
// Match the incoming request against the list of client-side routes
match({ routes, location: params.location }, (error, redirectLocation, renderProps: any) => {
if (error) {
throw error;
}
// Build an instance of the application
const store = configureStore();
const app = (
<Provider store={ store }>
<RouterContext {...renderProps} />
</Provider>
);
// Perform an initial render that will cause any async tasks (e.g., data access) to begin
renderToString(app);
// Once the tasks are done, we can perform the final render
// We also send the redux store state, so the client can continue execution where the server left off
params.domainTasks.then(() => {
resolve({
html: renderToString(app),
globals: { initialReduxState: store.getState() }
});
}, reject); // Also propagate any errors back into the host application
});
});
}

View File

@@ -17,6 +17,7 @@ export default class Home extends React.Component<any, void> {
<li><strong>Webpack dev middleware</strong>. In development mode, there's no need to run the <code>webpack</code> build tool. Your client-side resources are dynamically built on demand. Updates are available as soon as you modify any file.</li>
<li><strong>Hot module replacement</strong>. In development mode, you don't even need to reload the page after making most changes. Within seconds of saving changes to files, rebuilt CSS and React components will be injected directly into your running application, preserving its live state.</li>
<li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and the <code>webpack</code> build tool produces minified static CSS and JavaScript files.</li>
<li><strong>Server-side prerendering</strong>. To optimize startup time, your React application is first rendered on the server. The initial HTML and state is then transferred to the browser, where client-side code picks up where the server left off.</li>
</ul>
</div>;
}

View File

@@ -7,7 +7,8 @@ import { typedToPlain } from 'redux-typed';
export default function configureStore(initialState?: Store.ApplicationState) {
// Build middleware. These are functions that can process the actions before they reach the store.
const thunk = (thunkModule as any).default; // Workaround for TypeScript not importing thunk module as expected
const devToolsExtension = (window as any).devToolsExtension; // If devTools is installed, connect to it
const windowIfDefined = typeof window === 'undefined' ? null : window as any;
const devToolsExtension = windowIfDefined && windowIfDefined.devToolsExtension; // If devTools is installed, connect to it
const createStoreWithMiddleware = compose(
applyMiddleware(thunk, typedToPlain),
devToolsExtension ? devToolsExtension() : f => f