Server Side Rendering

(React Router Framework mode)

Essential React

01 Server-Side Rendering
02 Routing
03 Data Fetching
04 Forms & Actions

Server-Side Rendering (SSR)

React Rendering Mechanisms

Overview

Rendering Mechanisms

How does Pre-Rendering work?

How does Pre-Rendering work?

Advantages of Pre-Rendering

  • Search engine optimization (SEO), shareability
  • Performance (especially as perceived)

React Router can be used in two different modes:

Data

  • 'Classic' React Router
  • For client-side-rendered React apps
  • Focused on routing
  • Enables clientLoaders / clientActions

→ We used that in chapter 05

Framework

  • Brings loaders/actions (server), typesafety and intelligent code splitting
  • Enables SSR & static site generation
  • Wraps the data mode
  • Previously known as Remix

Structure of the new setup

Folder structure

Initial files of react router app folder
  • app/routes/*.tsx
    the component referenced in app/routes.ts
  • app/routes.ts
    configures the routes (more details in next chapter)
  • app/root.tsx
    describes the app's HTML document / root layout
  • public/*
    public asset files
  • react-router.config.ts
    build options
Initial files of react router app folder

app/root.tsx

app/routes.ts

react-router.config.ts

NPM scripts (package.json)

Routing

Routing in Framework Mode

General conventions

  • Routes are configured in a routes.ts file
  • Each route has two required parts: a URL pattern to match the URL, and a file path to the route module that defines its behavior.
  • The react component to be rendered on that route must be the default export of that js module.

index() indicates an index route

→ URLs / and /concerts

Static route segments

→ e.g. /about and/concerts/trending

Routes can be nested inside parent routes (e.g. layout,route).

→ URLs /login (layouts don't add any segments to the URL)

Dynamic route segments (parameters) start with :

→ e.g. /concerts/schlieren

Data Fetching

Loaders

Loaders

  • Single, optional loader per route (export loader)
  • Run on the server (only)
  • Define a HTTP endpoint: request → response
  • Result either serverside rendered and hydrated or fetched pre rendering
  • useLoaderData or loaderData props-field to access response data in component

blog.$slug.tsx

Modifying the HTTP response

Modifying the HTTP response

Return a Response object…

Modifying the HTTP response

…or throw it!

Exercise

Checkout SSR Samplecode and analyze

  1. Use the sample branch for chapter 10
  2. Use the dev tools network tab do analyze what is being fetched from the server. Use a prod build: npm run build && npm run start
  3. Stretch goal: Explore the <Link prefetch=""> attribute in PokeListEntry.tsx
  4. Stretch goal: Transform the data from the PokeAPI so that only the needed data is sent to the client

Insights

initial page load

consecutive page loads

Stretch goal: link prefetch option

Stretch goal: optimize data fetching

pages/list/ListPage.tsx

Results in less data sent around

Additional framework mode features

How can we redirect to a different route?

E.g. //blog

How can we redirect to a different route?

E.g. //blog

_index.tsx

Must be a named export called loader.

_index.tsx

→ redirects to blog.tsx

Other Useful Route Module Exports

Forms & Actions

Creating a form

blog.$slug.tsx

Let's start simple: We can use a native HTML form.

blog.$slug.tsx

On the server the form is processed by an action.

blog.$slug.tsx

Form data is read from the request using the standard Request.formData() method.

blog.$slug.tsx

The data can then be processed as desired (validated, stored, etc.).

blog.$slug.tsx

Like the loader, the action function can return a Response object.
Typically, a redirect is returned to implement the Post/Redirect/Get pattern.

blog.$slug.tsx

What will happen when the user clicks the Submit button?

→ It works! But it does a full document request: POST /blog/…

blog.$slug.tsx

The React-Router Form component together with the clientAction brings the expected SPA behavior

It still has the native form behavior as long as JS has not loaded yet.
→ Progressive Enhancement

blog.$slug.tsx

The React-Router allows to access the generated types for typesafety on this level.

It also provides typse for actions and clientActions!

Exercise

Checkout SSR Samplecode and analyze

  1. Use the sample branch for chapter 10
  2. Analyze what happens in the network tab upon submitting the form npm run build && npm run start
  3. Disable Javascript in the browser dev tools and analyze the behavior CTRL|CMD + SHIFT + P -> 'disable javascript'
  4. Stretch goal: think how you would go about validation while not breaking the progressive enhancement.

Insights

Progressive enhancement

  1. A full page navigation is happening, the server state updated and a fully rendered page returned. The PokeVisit count is lost.
  2. With javascript enabled the pasting from clipboard still works
  3. Without javascript, the clipboard and pokecount is lost. Core functionality still works.
  4. On client side navigation, the layout data is synced (update the profile in a separate tab)

Stretch goal: Thoughts about validation

  1. Have all critical validation within the action for security reasons
  2. Either enhance with HTML5 validation attribute for better UX
  3. Or use in addition the clientAction to perform validation before submitting for improved UX.

Things to consider when picking a mode

Client side rendered

  • In most cases simple and lightweight
  • Low hosting cost - just need a CDN
  • Many many projects have been built and run successfully and perform very well
  • Simpler mental model - all code only runs in browser

Server side rendered

  • Best possible performance needed
  • Added complexity due to part of serverside/clientside logic
  • Increased attack surface through all packages involved due to nodejs running
  • Can hide/abstract API's and acts as backend-for-frontend
  • Serverside dependencies can leak into the delivered bundle...
  • Hydration error... 😠

If unsure, go for client side rendering with framework mode (and clientLoaders)

Recap

We learned…

  • What server-side rendering (SSR) is
  • How to set up a React Router app from scratch
  • How to do routing in React Router framework mode
  • How to fetch data with loaders
  • How to create and process forms on the server
  • What to consider when deciding on SSR/CSR

Questions?