single-spa example: Rxjs shared state

In this example, I hope to showcase how to use a utility module that shares application state across multiple single-spa applications and multiple frameworks.

This example consists of:

  • root-config: shared HTML layout for microfrontends
  • navbar: basic Svelte application with navigation responsibilities
  • home: basic React application for logged-in users
  • login: basic React application for logged-out users
  • auth: utility module, using Rxjs and plain JavaScript

Setup

⚠️ This project relies on yarn for start and build scripts. You may need to make changes to scripts/lerna.json to get it working with npm client.

  • git clone git@github.com:filoxo/single-spa-example-rxjs-shared-state.git
  • run yarn bootstrap

Running locally

  • run yarn start
    • root-config runs on port 9000
    • auth runs on port 9001
    • navbar runs on port 5000
    • home runs on port 5001
    • login runs on port 5002
  • go to http://localhost:9000/
  • celebrate good times 🎉

Details

Live demo available at https://single-spa-example-rxjs-shared-state.netlify.app/login

Login and guards

  1. Log in using any credentials to show an error, as expected.

    • Also attempt going to /home route directly. It will redirect you back to login since there is no valid user.
  2. Log in using exampleuser with examplepassword as the password.
    Once logged in, you will be redirected to /home. If you try going back to /login you'll no longer be able to and will be redirected back to home.

Logout

Log out of the system using the "Logout" button in the navbar. Once again, after logging out, you will be redirected back to login.

Additional notes

These are implemented within the same repo using lerna for illustration purposes. In an organizational setting, each of the modules should be in its own repo (though a monorepo setup could still work with the right deployment setup).

Utility module?

Utility modules have lots of use cases, not just authentication, and are great for sharing common logic in one centralized place.

Why Rxjs?

Preference. I think Rxjs is extremely powerful when leveraged correctly, even though it has a high learning curve. However using Rxjs is just one of many options for sharing UI state

Why wouldn't I do this for *all* of my applications' state?

By doing so, you introduce:

  • tighter coupling between applications, which is a bad practice in a microservices environment
  • potential for bugs (eg. two apps modifying the same state at the same time)
  • potential performance issues due to re-renders of top-level components

See also "How can I share application state between applications?" and "Recommended Setup: UI State" on the single-spa documentation.

Why not do the auth check inside of the root-config?

Definitely could be done! The implementation of how auth happens is not the focus of this repo.

For an example of how to do that, check out the check-auth-in-root-config branch.