Microfrontend Application using Single-SPA framework

Single SPA allows several teams to develop and manage their dedicated JavaScript applications independently from each other. Individual applications work together as a whole, serving same user experience. Microfrontend is a Microservice based approach for web development.

Single-SPA is one of the best frameworks used for microfrontend apps. It has full support for Angular, React, Vue like technology and by using a single-spa framework, it is possible to create a loosely coupled microfrontend application.

Using Single-SPA framework, applications built in Angular & React are deployed separately, and run all micro applications into one application

Single-SPA framework has an official site you can check the deployed code and examples as well there.

I will build a microfrontend application using Single-SPA, the applications to be deployed are:

  1. Main Container Application (Vanilla JavaScript)
  2. Navigation Application for routing control (Angular)
  3. Dummy Application 1 (React)
  4. Dummy Application 2 (React)

Installing Single-SPA framework

I am going to use the CLI to setup my microfrontends. Therefore make sure you have NodeJS (>= 10.3.0) installed on your computer as well, if you wish to follow along. NodeJS installation is going to install the Node Package Manager (npm) which is needed to install the single-spa CLI:

npm install --global create-single-spa

# or
yarn global add create-single-spa
If you wish to have create-single-spa globally available

We will create our microfrontends in one repository for demo purposes, but with a production application, it is advisable to create a standalone git repository for each application.

// Creating a new directory 
mkdir microfrontend-application 

// Change into our directory
cd microfrontend-application
This directory will store all microfrontends

Step 1: Creation of navigation application

The navigation application will be built using Angular and its responsible for routing control, for the entire microfrontend. Run the below command in the microfrontend-application directory:

create-single-spa --framework angular 
// Initializing a single-spa application 
? Directory for new project .
? Project name (can use letters, numbers, dash or underscore) navigation
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
The package single-spa-angular@6.1.0 will be installed and executed.
Would you like to proceed? Yes
? Does your application use Angular routing? Yes
? What port should your project run on? 9001
Application will be built using angular

Update the microfrontend-application/navigation/package.json file to serve the application on port 9001:

"start": "ng serve --port 9001"
Modify the start script

In application main routing module, set up a wildcard route and add a provider:

import { APP_BASE_HREF } from '@angular/common';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '**', children: []},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [{provide: APP_BASE_HREF, useValue: '/'}]
})
export class AppRoutingModule { }
The two asterisks, indicate to Angular that this definition is a wildcard route.

Step 2: Creation of dummy application 1

The first dummy application will be built using React and we will set this as the landing page of our microfrontend. Run the below command in the microfrontend-application directory:

create-single-spa --framework react --dir dummy-1
// Initializing a single-spa application
? Which package manager do you want to use? npm
? Will this project use Typescript? No
? Organization name (can use letters, numbers, dash or underscore) thabo
? Project name (can use letters, numbers, dash or underscore) dummy-1
Application will be built using react

Update the microfrontend-application/dummy-1/package.json file to serve the application on port 9002:

"start": "webpack serve --port 9002"
Modify the start script

Step 3: Creation of dummy application 2

The second dummy application will be built using React and we will set this as a details application page of our microfrontend. Run the below command in the microfrontend-application directory:

create-single-spa --framework react --dir dummy-2
// Initializing a single-spa application
? Which package manager do you want to use? npm
? Will this project use Typescript? No
? Organization name (can use letters, numbers, dash or underscore) thabo
? Project name (can use letters, numbers, dash or underscore) dummy-2
Application will be built using react

Update the microfrontend-application/dummy-2/package.json file to serve the application on port 9003:

"start": "webpack serve --port 9003"
Modify the start script

Step 4: Creation of container application

The container application is responsible to load configuration, common decencies, design system, and sub applications built using Angular, React, Vue etc. Run the below command in the microfrontend-application directory:

create-single-spa --moduleType root-config --dir container
// Initializing a single-spa application 
? Which package manager do you want to use? npm
? Will this project use Typescript? No
? Would you like to use single-spa Layout Engine Yes
? Organization name (can use letters, numbers, dash or underscore) thabo
Provide your own organization name

There's a few configurations that need to be done to add the sub applications to the container application. Let's go through them:

  • Update the microfrontend-application/container/package.json file to serve the application on port 9000:
"start": "webpack serve --port 9000 --env isLocal"
Modify the start script
  • Let's create helper functions in the
  • file to help with registering the sub applications:
function prefix(location, ...prefixes) {
    return prefixes.some(prefix => 
        location.href.indexOf(`${location.origin}/${prefix}`) !== -1
    )
}

export function homePage(location) {
    return prefix(location, 'home')
}

export function detailsPage(location) {
    return prefix(location, 'details')
}
Tracks which app is currently visited based on the path
  • Update the src/thabo-root-config.js file assign paths for our sub applications:
registerApplication('@thabo/dummy-1',
  () => System.import('@thabo/dummy-1'), homePage);
registerApplication('@thabo/dummy-2',
  () => System.import('@thabo/dummy-2'), detailsPage);
registerApplication('@thabo/navigation',
  () => System.import('@thabo/navigation'), () => true);
Navigation app is always rendered on the window
  • Single-spa provides a layout engine that allows us to define where to render our applications on the dom. Modify the src/microfrontend-layout.html file:
<single-spa-router>
  <div style="height:98vh; display: flex;">
      <div style="height: 100%; width: 400px; background-color: aqua;">
          <application name="@thabo/navigation"></application>
      </div>
      <div style="width: 100%; background-color: pink;">
          <application name="@thabo/dummy-1"></application>
          <application name="@thabo/dummy-2"></application>
      </div>
  </div>
</single-spa-router>

See it in action

I will start up all the apps and visit the browser on http://localhost:9000 where the container app is being served on my machine:

This was just a basic setup of our microfrontend application, if you are having any issues please check the microfrontend-application repo on GitHub.

Summary

There you have it, we just created a microfrontend architecture composed of a one Angular application, two React applications and a Vanilla JavaScript app. I will build on this solution to add more functionality and deploy the final product to AWS!