This project is WIP.
This project was bootstrapped with Create React App with TypeScript. It has been modified to be an isomorphic application, with support to do server side rendering of the React web application (also the Redux state). The project also provides a way to create a RESTful Web API and is a POC to show how to use TypeScript for both server and client side.
When developing you can use yarn start
and use the standard development server that CRA provides. To access the development web server you can use port 3000
. When you run yarn start
a separate server is started that handles SSR and Web API endpoints. This server by default listens on port 3101
. To proxy API calls when using the development server, we use the proxy
feature provided by CRA to proxy API calls.
To use server rendering while developing, simply use port 3101
instead of 3000
in your browser.
n.b. you still need to re-run yarn start
when changing server side code (will not be like that in the future).
You can simply install dependencies by running yarn install
.
Some important infomation related to SSR.
You explicitly need to add a function fetchData
to your components, that you include in our React Router routes,if you want to do any prefetching of data before rendering the web application.
Example:
class LandingPage extends React.Component<LandingPageProps, {}> {
// Dependecies before rendering to client..
static fetchData(store: any) {
return store.dispatch(requestHealthCheck());
}
...
Redux state is rendered and attached to window.DATA
for the client to read it from and to preload the redux state. This is done like the follow code snippet shows:
import { Base64 } from 'js-base64';
const initialState = ((window as any).DATA !== null && (window as any).DATA !== '{{WINDOW_DATA}}')
? Base64.decode((window as any).DATA) : '{}';
/server/api/
includes all endpoints for /api/*
routes.
It should be noted that fetch
does not work relatively when running on server, a way around this is to do something like:
var ExecutionEnvironment = require('exenv');
let uriEndpoint = `/api/healthy`;
if (!ExecutionEnvironment.canUseDOM) {
uriEndpoint = `http://localhost:3101/api/healthy`;
}
...
fetch(uriEndpoint).then(...);
...
If we can use the DOM, then we are running on the client, where relative request work.
This is partly based on ideas from Ben Lu