Building Micro frontends with Single-SPA (Series 1) Get started with Single-SPA

Ella Min Luo
carsales-dev
Published in
6 min readDec 1, 2020

Background

From time to time, we all have worked on projects that have become very large, in the course of their lifetimes, more and more features get added. More teams are involved in building the front-end application. More models, functions, classes come out and they depend on each other, which makes front-end application becomes quite hard to maintain. It’s become a front-end monolith. It resource costs are large even when adding small changes. Nobody wants to touch it. It’s time to change it!

What are Micro frontends and Single-SPA?

To avoid the front-end monolith, we can try a Micro Frontends approach. It allows different teams to develop their own front-end application (micro-apps), using the language or framework that better suit their needs. When these micro applications are running, they are orchestrated and behave like a single page application.

One such JavaScript library, which can help build micro front-end applications is Single-SPA, with minimal extra effort.

Our Architecture

Our team Echo is building a global notification centre called Admin Portal. Admin Portal is the orchestration for all frontends applications of our team. It consists of below frontends applications: Blocklist, Logs Search, Template Management, User Management, etc. These applications used to sit together in one repo and build together as a monolith. As our team’s applications increased, the monolith becomes huge.

Old Big Picture of Admin Portal

After re-architecting the applications into micro front-end apps using single-spa, this is what it looks like:

New Big Picture of Admin Portal

Each application has its own repo and CI/CD pipeline. Blocklist, Logs Search, Template Management, User Management are registered as applications in Single SPA. Also, we have some shared components, like the top navigation bar, the app-selector, the account-selector etc, which are sitting in root config application. Some shared components are registered as parcels in Single SPA, some are registered as applications.

With this new architecture, we decoupled plenty of repo dependencies and boosted our development speed. The Admin portal is now more flexible and easily able to accommodate more applications registered.

Why choose Single-SPA?

We have compared four microservice approaches — router redirecting, iframe, web components and single-spa in multi areas for implementing micro frontends. The figure below shows the comparison result. According to our user story and team composition, Single-SPA is worth trying.

Different approaches to implementing Micro frontends

Benefits

Blog
Single-SPA Mechanism
  1. The team can choose a framework that better suits their needs to develop their child app.
  2. Minimum extra knowledge if you want to migrate your existing app to a Single-SPA child app. A few configuration updates are needed, then you can plug your child app in root app.
  3. No dependencies. It works on most browsers. You write the code in JavaScript and HTML.
  4. No security issues. It doesn’t bypass any JavaScript security check.

How to do it

Single-SPA implements Micro frontends by controlling the lifecycle of micro-apps. Detailed steps can be found on single-spa website.

A simplified version:

  1. A root config application that loads all the micro apps and necessary dependencies. It is configured so that it knows when to load/unload a certain micro app given a URL.
  2. The micro applications that are configured to launch in a micro-app mode. Basically, you add load/unload functions into the launch file and configure its routing to work in nested routes.

Single-SPA Application Lifecycle

API registerApplication is one of the most important and useful API. Once the application is registered, the lifecycle of the application can be well controlled through the activeWhen argument.

The lifecycle of Single-SPA Application

Register Before the application’s lifecycle starts, it needs to be registered in root config application and claimed when to be active.

Load After the application is registered and meets the condition to be active, the server will fetch the code of the application and execute. The application will be loaded only once when it’s the first time to be active.

Bootstrap (initialize) is called once to initialise the application. This happens before the first mount.

Mount is called when the application’s active status is set to be true and the application was unmounted.

Unmount is called when the application’s active status is set to be false and the application was mounted.

Unload is an optional lifecycle function. The user may call it manually when necessary. Once the application is unloaded, it will have to be re-initialized.

Single-SPA Parcels

Parcels are not one of the main features. It can be used in some special situations, e.g. reuse front-end components across micro applications in different frameworks. It has no routes, custom managed lifecycles and needs to be implemented imperatively.

In our Admin Portal. The below parts are implemented as parcels because they are shared components across all micro applications.
- No access page
- Not found page
- The spinner
- Top navigation bar

We also have a utility micro application that contains navigation pages, i.e. account selector and app selector.

Step by Step Example

To implement a root config application

Single-spa offers a CLI called create-single-spa to automatically generate and manage webpack and babel configurations.

Install the CLI tool globally

npm install --global create-single-spa

Run below to create a root config application

create-single-spa --moduleType root-config

The project file structure will look like this:

Project File Structure Example for Root Config App

The file index.ejs enables the usage of SystemJS and import maps as a module loader for the micro frontends. It implements loading registered micro applications to root config application.

In production, we turned on webpack filenameHashing and import maps from a CDN for better caching and deployment version control.

The file echo-root-config.js indicates how root config application uses API registerApplication of Single SPA to register micro apps and when micro apps are active.

To migrate an existing Vue app to Single-SPA mode

Use vue-cli-plugin-single-spa to automatically set up the existing app.

vue add single-spa

It will:

  1. Set up the webpack config in single-spa mode.
  2. Install single-spa-vue.
  3. Adding lifecycle functions to main.js to make it single-spa ready.
  4. Add set-public-path.js.

After migration, the project file structure will look like this:

Project File Structure Example for A Micro APP

The file main.js implements required bootstrap, mount, and unmount lifecycle functions to hook with root config application.

The files main.nosinglespa.js and .env.nosinglespa are our customised entry to run the micro application in no Single SPA mode, which allows us to test the app isolatedly. Dev tools import-map-overrides and single-spa Inspector are alternatives to make developers’ life easier without running too many apps locally.

The file set-public-path.js is to set the public path of your application and let webpack knows where the generated bundle will be hosted.

The file babel.config.js is just a default Babel preset used in all Vue CLI projects.

The file vue.config.js leverages the configuration of webpack external to reduce the size of the bundle package and enable webpack filenameHashing for caching.

To build a new Vue app in Single-SPA mode

We can use create-single-spa CLI to scaffold a micro front-end version Vue app.

Run:

create-single-spa --framework vue

Then follow the prompt, the Vue app will be created automatically.

Conclusion

The single-spa library allows us to build micro frontends in an agile way. It decouples the development of multiple front-end projects and makes them run together smoothly. Hope our experiments could benefit you as well :D

Links

Building Micro frontends with Single-SPA (Series 2) Dependency resolution via SystemJS

Creating a registered application in Single-SPA

How to migrate an existing app to a Single-SPA micro app

Single-SPA Parcels

Single-SPA Microfrontend Types

Single-SPA Applications API

--

--