Micro-frontends, url design and routing
What is routing?
Applications have their own data architecture and tree typically mapping to a navigation or menu capability. No matter the type of application, we will have an entry point or landing or homepage, that is the top level of our application. For example for this site, the tree looks like this.
|-- homepage
|-- architecture
|-- frontend monoliths
|-- decoupling a monolith
|-- modular apps
|-- ...
|-- frameworks
|-- ecosystem
|-- app types
|-- ...
|-- standards
|-- user experience
|-- operations
|-- other resources
(I truncated the tree for the sake of brevity). We have up to 3 levels of depth and the users can navigate the subtree using the side-navigation. To access those sub items, we need to provide the system with a reference to them.
URIs and paths
In simple terms, let’s say that each one of those items in the tree are a resource, and that to access it, we need a path. This is valid for resources in the context of a file system and also in the context of the web. To identify those resources and the path to them, we have URI that stands for Uniform resource identifier
.
For example, if think of microfrontend.dev
index file as a resource in a server, and the tree is in its docs
folder, that is inside of the content
folder, that is inside of src
, as per Astro -the framework I built this side with- conventions, then the path to it is,
~/src/content/docs/index.mdx
(where ~ is the root).
Locators, routers and the internet
I don’t want to get to technical here and explain networking, routers, and protocols (I’m writing another book about APIs that goes into that!) but just as we have URIs to locate resources in, for example, a POSIX compliant file system, we have URLs that stands for Uniform resource locator
to find a resource with protocols like http
, mailto
, ssh
-and file
, too, to be honest.
Designing URLs
Now when we’re building an application, and creating our tree, we will need to create it in a way that, from a user experience perspective, makes sense and offers a good experience. When the frameworks or tools we’re using, even the servers we are using, do not offer the possibility of generating human readable URLs, we may need to resort to vanity mechanisms which are also SEO friendly and compliant.
Of course, that’s for accessing a resource just to read it, like we do with the GET
verb of the http protocol. Sometimes when we’re performing POST
or other operations, the URLs get a lot more messy because of additional parameters.
But let’s focus on how our applications understand how to access those resources, internally.
If you haven’t already, please read Frameworks and App Types, to better understand the next session.
MPAs and routes
Multi-Page Applications routes are typically static and defined via server configuration that defines the routes and access rules, and sometimes there are other routing modules in the middle. Servers direct the request to a specific locator and load the page. There are multiple mechanisms and protocols involved in those request/response dynamics, with the server rendering the page and the content requested. Each route inside of an MPA is a different page and results in a full reload.
SPAs and routes
Single Page Applications dynamically build their routes and render the content. Many frameworks implementing SPAs and CSR offer has routing mechanisms to avoid reloading the shell and preserve application state.
And metaframeworks implementing SSR?
If you haven’t read about metaframeworks or SSR do so now. Metaframeworks equipped with SSR or SSG capabilities, typically implement file-based routing, that maps to MPAs mechanisms for delivering static content. Although it’s important to mention that coupled with hydration, the router may do computations server side, to fetch resources from different locations, and recompose them, sometimes generating routes on the fly, as well.
Considerations
It’s important to consider the challenge of routing in the context of horizontal splits when composing micro-frontends, especially when done with multiple frameworks. Stitching those micro-parts together, and keeping their internal routing capabilities to access nested components and content, while preserving a unified state across the view or split, is one of the most difficult tasks when building micro frontend applications.