Building Micro-Frontends
Book summary
📝 Draft version:
Notes for reading club at work!
Overview
Scaling Teams and Projects. Empowering Developers
The Frontend Landscape
Discusses the thought process for arriving at Micro-frontends & provides an overview of different architecture available for frontend development.
Micro-Frontend Applications
- Inspired by Microservices architecture
- Breakdown monolithic codebase into smaller parts
- Designing & Encapsulating API is the easiest part.
- Adding High flexibility and good encapsulation between domains, overall observability, automation, discoverability of a sytem is complex
“Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization’s communication structure.” - Melvin Conway’s law “How Do Committees Invent?” Thompson Publications, Inc., 1968
Conway’s law could be mitigated with the inverse Conway maneuver, which recommends that teams and organizations be structured according to our desired architecture and not vice versa.
Mastering different architectures and investing time in understanding how many systems work allow us to mitigate the impact of Conway’s law, because it gives us enough tools in our belt to solve both technical and organizational challenges.
What it offers
- Organisational agility
- Better time to market
What is needed
- Combined with microservices & strong engineering culture
- Where everyone is responsible for their own domain
Questions
- Flexibility
- Encapsulation
- Observability
- Discoverability
Single Page Applications
- Few JS files encapsulate the entire application
- Client downloads entire application just once at the beginning of life cycle
- Communicates with API (Server side)
Pros
- Better User experience like native apps
- routing is handled at client side, for each view change is URL is re-written
- enabling user to bookmark & manage history
- Flexibility to have
Fat Client
&Thin Server
orFat Server
&Thin Client
Fat Server
&Thin Client
can be good for cross-platform applicationsFat Client
&Thin Server
can be good for desktop applications - offline data- Choosing FatX or ThinX depends on the requirement
Cons
- Initial load time could be longer, as the entire application is downloaded
- In unreliable network connections on mobile devices it could be a huge setback
- SEO crawler would have tough job indexing the contents served by SPA
- Low-end hardware might not be able to handle the heavy bundle of SPA
- Managing a large scale application with distributed/collocated teams, could be challenging, with difference mix of approaches, thus slowing down the operation and becomes a hidden cost of the app development/maintenance
How to mitigate
- Code splitting
- Lazy loading
- PWA - (Service Workers caching strategies)
Example
Usually, when we want to provide better indexing for an SPA, we tend to create a custom experience strictly for the crawler. For instance, Netflix lowers its geo-fencing mechanism when the user-agent requesting its web application is identified as a crawler, rather than serving content similar to what a user would watch based on the country specified in the URL. This is a very handy mechanism, considering that the crawler’s engine is often based in a single location from which it indexes a website all over the world.
Isomorphic (Universal) Applications
- The code between server and client is shared and can run in both contexts.
Pros
- Benefits in time to interaction, SEO, A/B Testing
- Allows the server to retrieve the data to display frm DB/API/Service aggregate it, pre-render it and sends the generated html saving round trips between client & server
- Helps crawler with a HTML page with all information ready to be indexed.
- Can follow flexible hybrid approach in sharing the code between contexts. Certain part can be SSRd (Server Side Rendered) which could increase the time to interact; lazy load additional JS files, thus enabling the SSRd html as an SPA.
- CSS, HTML skeleton can be loaded quickly and completely delegate the data rendering and integration to the server.
- A/B testing can be easily done where a specific experiment to a specific user can be served by the server.
Cons
- Scalability issues could arise as we are generating pre-rendered HTML on the server
- Same as SPA, Isomorphic apps could suffer when working with distributed/huge team
How to mitigate
- Use CDNs to implement right caching strategies and avoid hitting origin servers.
- Implement BFF(Backend for Frontends) by decoupling the API Implementation/Maintenance responsibilities.
Static Page Websites
- Old school click and wait for the page
- Used for quick websites that is not meant to be there for a long period. e.g. Advertising a product
- Created by small teams or individual contributors
- Could be a sandbox project to play with new technologies or new practices or to do RDD (Resume Driven Development) 😉
JAMStack
- JavaScript, APIs, Markup
- Fast, Secure, Dynamic Apps without web servers.
- Final output is static artifact composed of HTML, CSS & JS, which can be served by CDN.
- There are popular React(Gatsby, Next) & Vue(Nuxt, Gridsome) based solutions available.
Pros
- Better Performance & Cheaper Infrastructure, as they can be served by CDN
- Greater scalability as they serve static files
- Higher security due to decrease of attack surface. Refer DDoS Attack.
- Easy Integration with headless CMS
- Frictionless developer experience
Summary
- In FE Ecosystem Different architectures evolved to solve different problems
- The missing piece: A solution that allow scaling with hundreds of developers on the same project
- Micro-frontends are the missing piece
- It will never be the only architecture for FE Projects, yet it provides options to create FE projects at scale.
- Learning Micro-Frontends starts with their principles, analyzing how these principles should be leverages inside an architecture & how much they resemble micro-services.
Review Session - 1
Review Session - 2
Micro-Frontend Architectures and Challenges
Micro-Frontend Decision Framework
Some architectural decisions will need to be made up front because they will direct future decisions, like how to define a micro-frontend, how to orchestrate the different views, how to compose the final view for the user, and how micro-frontends will communicate and share data. These types of decisions are called the micro-frontends decisions framework. It is composed of four key areas:
- Defining what a micro-frontend is in your architecture
- Composing micro-frontends
- Routing micro-frontends
- Communicating between micro-frontends
Micro-Frontends Composition
The second decision is understanding where we want to compose micro-frontends, here we have 3 options to choose from:
- client-side composition
- edge-side composition
- server-side composition
Client-side means implementing techniques like an App Shell loading single page applications, for instance, check out Single-SPA project, with iframes like Luigi framework or via a library using client-side transclusion technique.
Implementing over the edge would mean using CDNs capabilities like Edge-side includes (not always available in all the CDN providers or not fully implemented) or via computation happening on/near the edge (bear in mind there are restrictions in how much logic we could run with a solution like lambda@edge for instance).
Finally, on the server-side, there are plenty of frameworks like Ara Framework, Open Components, Piral or Tailor.js and many others.
When we decide to go with a vertical split we should aim for a client-side composition using Single-SPA. Instead, when we decide to identify our micro-frontends as a single part of a view we have all the options available (client-side, edge-side and server-side).
Micro-Frontends Routing
After defining our micro-frontends composition strategy we need to decide how we want to route our views. This time the decision is not mutually exclusive, we can decide to route client-side and adding logic on the edge or having the routing logic on the client or server only.
In this case, the suggestion is to be coherent with the composition part.
For client-side composition, use the app shell for mapping the routing logic, For server-side composition, use the webserver for managing the routing logic. For edge-side composition, Rely on the URL associated with a page.
Review Session - 3
Say Hello