In this post, I am going to walk you through on how to create Micro-Frontends with Glimmer.js using the single-spa library.
We are going to create a simple application like a Starwars wiki with just only two pages for the list of planets and people references in Star Wars movie. The planets page will list the planets from the films and their details. Similarly the people page will list the characters from the movies and their details.
You can view the Glimmer Micro-frontends in action here and the source code is hosted in this github org.
Before diving into the tutorial, let's make ourselves clear about the tools and technologies we are going to use.
Micro-Frontends
Micro-Frontends is about extending the micro-service idea to frontend development. It is a collection of techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently.
Glimmer.js
Glimmer is one of the fastest DOM rendering engines, delivering exceptional performance for initial renders as well as updates. Architected like a virtual machine (VM), Glimmer compiles your templates into low-level code so it can run as fast as possible—without sacrificing ease of use. Glimmer VM powers the components in Ember.js
single-spa
single-spa is a JavaScript router for front-end microservices. With single-spa you can use multiple frameworks in a single-page application, allowing you to split code by functionality and have Angular, React, Vue.js, etc. apps all living in harmony. single-spa makes them work together and won't load them until they're needed.
single-spa-glimmer
single-spa-glimmer is a helper library that helps implement single-spa registered application lifecycle functions (bootstrap, mount and unmount) for for use with Glimmer. For more information, check out the github repository.
One important thing we are doing inside this library, especially inside the mount lifecycle hook is the below:
functionmount(opts){returnPromise.resolve().then(()=>{// Turning off validator registration for allowing multiple glimmer apps in same pageglobalThis[Symbol.for('GLIMMER_VALIDATOR_REGISTRATION')]=false;const{renderComponent,App,root,owner}=opts;constelement=document.getElementById(root);renderComponent(App,{element,owner,});});}
We are deliberately turning off the @glimmer/validator registration, to allow multiple Glimmer apps co-exist within a single HTML page. Currently, this is not possible, but thanks to the above workaround proposed by John Griffin in this issue he had created in the glimmer-vm repository.
Recommended Setup by single-spa core team
The single-spa core team recommends a default setup to create micro-frontends with any framework based on a set of conventions which will help us to scale our micro frontends in the long run.
We are going to follow the below setup:
glimmer-micro-frontends
|- root-config
|- navbar
|- people
|- planets
root-config
This is the host app that manages all the other micro frontends using single-spa.
Let's see how to create the root-config app using the CLI:
Invoke the create-single-spa command at the terminal
create-single-spa
It will present you with a set of options like directory, type of application. With create-single-spa you can create different type of applications like single-spa-application, in-browser utility and root-config. You can read more about the different type of modules here.
For this project you have to choose the single-spa root config option and follow the other successive prompts.
? Directory for new project
? Select type to generate (Use arrow keys)
single-spa application / parcel
in-browser utility module (styleguide, api cache, etc)
❯ single-spa root config
Once the generators are done, you will have a src folder with two files. index.ejs is the html template for our host app where we will have the placeholders for the other micro frontends.
<templateid="single-spa-layout"><single-spa-router><applicationname="@glimmer-mf/navbar"></application><divid="navbar"></div><main><routedefault><pclass="mfe-info">
This example project shows independently built and deployed microfrontends that use <ahref="https://glimmerjs.com">Glimmer.js</a> and <ahref="https://single-spa.js.org">single-spa</a>. Each nav link above takes you to a different microfrontend.
</p></route><routepath="people"><applicationname="@glimmer-mf/people"></application></route><routepath="planets"><applicationname="@glimmer-mf/planets"></application></route></main><footer><p><ahref="https://github.com/glimmer-mfe">Github</a></p></footer></single-spa-router></template>
And the next file will be root-config.js. This is where we will register all our Glimmer micro frontends using the single-spa registerApplication
We are making use of the single-spa-layout engine here. The layout engine provides a routing API that controls your top level routes, applications, and DOM elements. Using single-spa-layout makes it easier to accomplish the following:
And finally we need to hook up the lifecycles for the Glimmer app with the single-spa library in src/index.js. We need to give the single-spa-glimmer function the parent Component, the application owner object with the list of services that needs to be injected, the renderComponent function from @glimmer/core and the DOM element id for mounting the parent component. The id will be the same as the application name we gave in the root-config markup earlier.
For example, if the application name is @glimmer-mf/people the DOM element id will be single-spa-application:@glimmer-mf/people which will be automatically created and added to the DOM by the single-spa layout engine, whenever the /people url is visited in the app.
We have to do the above step for each Glimmer app we create.
people
This micro frontend is for the people page and list the people and their details using the Starwars API SWAPI.
I am not going to discuss in depth about the functional code to fetch the api and show the list of people in this app. That has already been discussed in my previous blog post here.
Instead, we will take a look at the webpack.config.js for the Glimmer apps, because we need to tweak it a little bit, to build for single-spa compatibility.
The significant thing to notice in the config is the libraryTarget property which is assigned the value system to make the build compatible with single-spa, since it uses System.js under the hood. You can read more about the recommended build tools config for different bundlers like Webpack and Rollup.
I have made a sample repo to re-use for single-spa in Glimmer with webpack, so that you don't have to start from scratch for creating Glimmer Micro-Frontends with single-spa.
This is how the people app will look like in action.
planets
The planets micro frontend is almost similar to the people micro frontend except it uses the planets api from SWAPI.
Running the app
Once you have done all the above things properly, you can start the Glimmer microfrontends and see them in action in the local environment by firing up yarn start from the root-config app.
yarn start
This will start the webpack-dev-server in the port 9000 by booting up the app and you can view the app in localhost:9000
What's next?
We still have a long way to go in this approach of using Glimmer to create micro front-ends. There are some challenges with respect to routing within the apps which we need to address.
This is an entirely new approach of creating Micro-Frontends using Glimmer.js for all the frontends. Since Glimmer is lightweight and fast, the performance benefits supersede all the other boilerplate code we need to have for routing and rendering components.
You are not tied with a particular framework implementation, you are free to choose any framework to add to the micro frontends here with other Glimmer apps.
You don't have to redeploy other Glimmer apps if you change your dependencies with respect to the other micro frontends, because single-spa registers your dependencies from where you have hosted the other micro-frontends.
You can dynamically mount/unmount you apps with the single-spa-inspector browser addon provided by the single-spa team in your browser. It supports Chrome and Firefox browsers.
You can also override the apps at runtime inside the browser with the addon for testing any micro-frontend in your local development environments.
Please let me know your thoughts in the comments section, about building Glimmer micro-frontends using single-spa and also check out single-spa for building micro-frontends in other frameworks like React, Vue, Svelte, Preact, etc.,