Frontity Docs
  • ยป Welcome to Frontity
  • ๐Ÿš€Getting started
    • Quick start guide
  • ๐Ÿ“ƒAbout Frontity
    • Frontity features
    • Browser support
    • Get involved
  • ๐Ÿ“šCore Concepts
    • 1. Project
    • 2. Settings
    • 3. Packages
    • 4. Roots
    • 5. State
    • 6. Actions
    • 7. Libraries
    • 8. Namespaces
    • 9. Styles
  • ๐Ÿ—๏ธArchitecture
    • Decoupled Mode
    • Embedded Mode
  • ๐ŸŒŽDeployment
    • Deploy Frontity using Vercel
    • Deploy Frontity on Layer0
    • Deploy Frontity on Heroku
  • ๐ŸŒ—Isomorphic React
  • โšก๏ธ Perfomance
    • Caching
    • Link prefetching
    • Lazy Loading
    • Code Splitting
  • ๐Ÿ”ŽSEO
  • ๐Ÿ“–Guides
    • Setting the URL of the WordPress data source
    • Using Environment Variables in a Frontity project
    • WordPress requirements for Frontity
    • URLs in a Migration from WordPress to Frontity Decoupled Mode
    • Frontity Query Options
    • Redirections with Frontity
    • Understanding a Frontity project
    • Add a new Frontity package or theme to your project
    • How to share your Frontity project
    • Understanding Mars Theme
    • Working with processors
    • How to process page-builder content in Frontity
    • Keep Frontity Updated
    • Troubleshooting
    • JavaScript
    • React
  • ๐Ÿ‘Contributing
    • How to contribute?
    • Contributing Guide
Powered by GitBook
On this page
  • Table of Contents
  • Server-side Navigation and client-side Navigation
  • Initialization of a Frontity app
  • Frontity Lifecycle Initialization Actions
  • Creating different entry points
  • Server-side code and client-side code
  • Server-side only code
  • Client-side only code
  • Both server-side and client-side code

Was this helpful?

Isomorphic React

PreviousDeploy Frontity on HerokuNextโšก๏ธ Perfomance

Last updated 3 years ago

Was this helpful?

When developing a Frontity project or package the React code (used in your custom theme) should be (also called universal).

This means that all the code in a Frontity project should be prepared to be executed both on the server-side and on the client-side.

This is especially important when we import npm packages for use in our Frontity project. For example, is native in client-side only and so is not available server-side. Therefore is recommended.

Another example is the . You should not try to access any of the properties or methods available in the window object from code that is going to be executed on the server, as the code will fail since the window object is only available in the browser.

Table of Contents

Server-side Navigation and client-side Navigation

Every time we access a page on a Frontity site the first load is rendered on the server. Once the initial server-side render (SSR) is complete the HTML is sent to the client (along with React hydration) and then the ensuing navigation is done in the client-side (CSR). ().

Let's take a look at some possible navigation examples as they would occur in an Isomorphic React App:

Scenario A (SSR)

If we enter the URL /home in the browser's address bar and press Enter, then the page with the slug home is rendered in the server and served to the client. If we enter the URL /contact in the browser's address bar and press Enter, then the page with the slug contact is rendered in the server and served to the client.

In these two cases, a SSR (Server-Side Render) process has taken the React code and created the proper HTML with the proper content that is "served" to the client so it can be displayed to the user.

Scenario B (SSR & CSR)

But consider the case where we enter the URL /home in the browser's address bar and press Enter, and then once the page has loaded in the browser we go to the /contact URL from a link in the page.

What then happens is:

  • the page with the slug home is rendered in the server and served to the client (as before)

  • the page with the slug contact is this time rendered in the client and displayed to the user

In this "Scenario B", we can call the navigation process to get to the home page "server-side Navigation" and the navigation process to get to the contact page "client-side Navigation"

We can also refer to these as a Server-Side Render process (SSR) in the case of the home page, and a Client-Side Render process (CSR) in the case of the contact page.

So, as you can see from the above image, this is something that we need to bear in mind when developing a React theme with Frontity.

Luckily, ALL the tools included with Frontity provide this isomorphic behavior out of the box (i.e. they ensure behavior that works both on the server-side and on the client-side).

Initialization of a Frontity app

The initialization (or Bootstraping) of a Frontity site happens when we do Server-side Navigation (Server-Side Render, SSR), this when we do either:

  • type a URL of a Frontity site in the browser's address bar and press Enter, or

  • reload a URL of a Frontity site (e.g. by hitting the refresh button in the browser on a page that has been rendered in CSR)

In this process (i.e. the request of /home in the diagram above) Frontity does the following:

  1. Server generates the HTML for the requested page

  2. Server sends the HTML to the client

  3. Client hydrates the React app in top of the HTML rendered

Once these have occurred React can then take full control of the app and the navigation of the site (through clicks on links) will be handled in the client-side (i.e. the request of /contact in the diagram above):

  1. Client (React) requests the data from the WordPress server (if not already in the state)

  2. Client (React) displays the proper HTML with the proper content and data

Frontity Lifecycle Initialization Actions

Some of these actions that you can 'hook' your code onto occur on the server-side, and some on the client-side - thus giving you the ability to specify not only when your code is executed, but also where it is executed.

On the Server Side:

  1. Execution of the init action

  2. Execution of the beforeSSR action

  3. Server generates the HTML of the requested page

  4. Execution of the afterSSR action

  5. Server sends the HTML to the client

On the Client Side:

  1. Execution of the init action (again)

  2. Execution of the beforeCSR action

  3. Client hydrates the React app in top of the HTML rendered

  4. Execution of the afterCSR action

Creating different entry points

By default Frontity will create the final bundles that will be used in the server-side and in the client-side from the index.js file in the src folder of the theme package you're using for your Frontity project.

  • client.js โ†’ the entry point of our app when client-side takes controls

  • server.js โ†’ the entry point of our app when server-side takes controls

If Frontity finds those files, it will import the server.js one in Node.js and the client.js one in the browser, and it will ignore the index.js file - which can, nevertheless, still exist.

Using beforeSSR is independent of using a server.js file. You can add a beforeSSR function to your index.js and it works fine. The code, of course, will make it into the client bundle, but the action wonโ€™t be called there (unless you call it manually).

The main use cases where you may want to use two separate client.js and server.js files are:

  • If you need to access Node.js libraries, such as "fs" or "path" , because they will fail if present in the client bundle ("dot-env" for accessing environment variables, for example).

  • If the code contains something that cannot be exposed to the client, for example authentication details such as a hardcoded API key.

Server-side code and client-side code

Due to the isomorphic nature of sites built with Frontity there will be some parts of the code of your Frontity project that will be executed only on the server, some parts that will be executed only on the client (i.e. the browser), and some parts that will be executed on both.

Server-side only code

During the initialization of a Frontity app, the following parts of the code are executed only on the server

As the code only runs on the server we can safely make use of environment variables inside of, for example, the beforeSSR action.

Client-side only code

During the initialization of a Frontity app, the following parts of the code are executed only on the client-side (i.e. in the Browser).

When components are โ€œhydratedโ€, and also whenever any Client-side Navigation occurs, any hook defined in a React component (such as useEffect) will also be executed only on the client-side.

Both server-side and client-side code

The rest of the code inside the React components in the project will be executed either server-side or client-side depending on if we're doing Server-Side Navigation or Client-Side Navigation.

Isomorphic Workflow

Frontity provides several actions, namely , that are executed at specific moments in the initialization process. You can 'hook' functions onto these actions to ensure that they are executed at the appropriate moments in this lifecyle.

Frontity Lifecycle Initialization Actions

However, you can actually create two different for your React theme package in Frontity. So, instead of having an index.js you can have the following two files:

You can define the appropriate in either, or both, of these files (client.js and server.js), or in the default index.js.

If you are using a heavy library on the server that will increase the size of the client bundle unnecessarily. For example, you can use to decode entities in the server.js, but it . You can therefore use , which is available in the browser and so is essentially free, in the client.js instead.

The

Functions "hooked" onto the and actions

As the is executed at Build Time, this file also has access to server-side packages and environment variables.

Server-side only code

The

Functions "hooked" onto the and actions

This means that we can safely make use of, for example, the or the native inside of the useEffect hook.

Client-side only code

During the initialization of a Frontity app the function "hooked" onto the action of the is executed in both the server and the client-side.

This means that in this part of the code we should use isomorphic versions of libraries, for example using an isomorphic (as provided by the package) to fetch resources from the network as it'll work in both server and client-side.

Both Client-side and Server-side code
๐ŸŒ—
Open drawing
Frontity Lifecycle Initialization Actions
entry points
Frontity Lifecycle Initialization Actions
he
weighs in at 73Kbs
new DOMParser().parseFromString
Open diagram
beforeSSR
afterSSR
frontity.settings.js file
beforeCSR
afterCSR
window object
fetch
fetch
the one
frontity
isomorphic
fetch
a fetch that works in both client-side and server-side
window object
This enables your site to remain SEO friendly, while also maintaining a good UX
Server-side Navigation and client-side Navigation
Initialization of a Frontity app
Frontity Lifecycle Initialization Actions
Creating different entry points
Server-side code and client-side code
Server-side only code
Client-side only code
Both server-side and client-side code
server.js file
client.js file
init
index.js file