/react-ts-ssr-app-boilerplate

React + TypeScript server-side-rendered application boilerplate, styled with styled-components.

Primary LanguageTypeScript

React + TypeScript SSR Application Boilerplate

All 100s in Lighthouse (with fireworks since 5.1.0 😁)!

language: TypeScript frontend: React backend: restify style: styled-components

This is a boilerplate project, set up for writing a server-side rendered PWA with React + TypeScript, styled with styled-components. It uses React Router DOM for routing and React Helmet as a document head manager.

Note: at this point, server-side caching is not supported. But, after all, do you really need to cache a PWA's content on the server? In the end, your clients are only ever going to request a server-side rendered page on their first visit, or when you decide to update your service worker cache (on the client). Nonetheless, I'll try to make server-side caching possible (you can see some comments in src/server/servers/app/index.tsx in which I lay down a basic concept for caching).

Getting started

To use this boilerplate, just clone (or simply download) the repository to your computer, and install the required dependencies with npm i (or npm install). Then change what you need to change in package.json (package name, author, etc. – but not the license!).

Building your app

Feel free to tweak the webpack configuration to your needs!

Development

For quick development, you can npm start (or npm run hot:start). This will fire up an instance webpack-dev-server, which will allow to see the changes you make to your code as soon as you make them. Note that this approach will neither have server-side rendering, nor the service worker.

If, instead, you want to try server-side rendering or check out the service worker, but still maintain the ability to debug with source maps in the browser, you can npm run development:dist. This will build client, server and service worker, giving you a production-like experience with all debugging tools at your disposal. The server uses a self-signed certificate for localhost, which is located in ssl/development. You may want to install it beforehand, or replace it with your own.

Production

Creating a production build is as easy as running npm run production:dist. This will generate an output very similar to the one that is output by development:dist, but with production optimizations and without debugging tools such as source maps. In production mode, the server uses the certificate located in ssl/production. Be aware that, because it is specific to your own domain name, the certificate is not provided by default.

Running your app

Server-side rendering

Whether you created a development or a production build, you can npm run ssr:start to launch a Restify server that will render the app before sending it to the client.

Client-side rendering

This boilerplate's main purpose is server-side rendering, but you can disable it if you don't want to create your own server and just host static files. To do so, just delete index.html and ssr.bundle.js and rename index.csr.html to index.html.

Just a reminder: don't forget to reroute all traffic to index.html if you choose client-side rendering!

The build's output, in detail

Note that you probably don't care about this, but, in case you really did, here is a more detailed explanation of what is output when building the app:

  • dist/public, which contains files that look like they can all be served statically, but some shouldn't: the files index.html ssr.bundle.js are actually used for server-side rendering, so serving these files statically will result in an error, as the bundle calls ReactDOM.hydrate, which requires the app's root to already contain rendered HTML. To render your app solely on the client side, see Client side rendering.
  • dist/server: this directory actually contains the JavaScript files that run the server. They create a server with Restify, and, for each request, dynamically render the app with ReactDOM/server's renderToNodeStream function, which allows for a very low TTFB (time to first byte).
  • dist/client, that just contains the unbundled files for the client. These are imported by the server to render the app.