Getting started
To start creating your universal application, a few files and configurations are required.
Configuration file
This file is shared across both the server middleware, and client application.
// Import your root component
import RootComponent from './RootComponent';
// Import your route definitions
import Routes from './Routes';
export default {
entry: {
rootComponent: RootComponent,
routes: Routes,
template: './index.html',
},
};
Creating a server app
This file will need to be run, along with any client side workflow (I.e. Webpack, Gulp). TinyServer will ensure all route definitions are handled internally, while all un-matched routes will be handed off to the next middleware.
// ./server.js
import express from 'express';
import { createTinyServer } from 'tiny-universal';
// Shared config for both server and client
import config from './tinyConfig';
const app = express();
// Create an instance of TinyUniversal
// to be used as middleware
const tinyServer = createTinyServer(config);
app.use(tinyServer);
app.listen(8080);
Creating a client app
Your root application component should be created as any normal root React component is created, however we'll wrap this component and ensure the routing context is added to it. Once again, use your external config file and apply it to your root component.
// ./client.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createTinyApp } from 'tiny-universal';
// Shared config for both server and client
import config from './tinyConfig';
// Create an instance of TinyUniversal
// to be used as your React application
const tinyApp = createTinyApp(config);
ReactDOM.render(tinyApp, document.getElementById('root'));
Defining your routes
In their simplest form, routes allow you to define navigation in your application. Following React's declarative nature, your routes can be defined as a stateless component. Each route requires at least a path
and a component
defined. The path
is will be matched to the current URL pathname, and the component
is the React component that will be rendered when the route is active.
It's important to note that each time the route is active, the component will be both mounted
and unmounted
respectively, so that you have complete control over any mounting requirements.
// ./Routes.js
import { Route } from 'tiny-universal';
const Routes = () => (
<Route path="/" component={Home} />
);
export default Routes;
If you have more than one route, simply wrap them in a root element.
// ./Routes.js
import { Route } from 'tiny-universal';
const Routes = () => (
<div>
<Route path="/" component={Home} />
<Route path="/foo" component={Foo} />
<Route path="/bar" component={Bar} />
</div>
);
export default Routes;
Add an index file
Your index file is served statically through Express and can contain anything you need to mark-up your application, however, it is vital that <% appRoot %>
is present. TinyUniversal will search for this token in the template, and replace it with the server rendered root component, and also pass any serverProps through to the client app.
<!doctype html>
<html>
<head>
<title>My TinyApp</title>
</head>
<body>
<div id="root">{appRoot}</div>
<script src="/bundle.js"></script>
</body>
</html>
Creating your root application component
Lastly, you'll need a root component. There doesn't have to be anything special about this component, rather, it's the one that is supplied with the TinyUniversal config, and both the server and client app will use it. To render the Router, simply import it and position it wherever suits best. It's important to note that you don't need to add the <Router />
here, your application will be wrapped within the <RouteProvider />
which gives routing context to your application.
import React from 'react';
import { Router } from 'tiny-universal';
const RootComponent = () => (
<div>
<h1>My TinyUniversal application</h1>
<Router />
</div>
);
export default RootComponent;
// TODO