This is a living document. Come back often to get updates.

User Experience Considerations

Micro frontends and performance

Consistent User Experience

When designing a decoupled architecture, particularly the decoupled frontends, we will need to make sure the user experience remains cohesive and coherent, across the many micro parts. This is one of the reasons why governance is vital to succeed.

Imagine loading a page composed of several micro applications, and each one of them has a different representation of state via the UI. Just a simple UI element, like a link, where the state (active, visited, focused) is represented in an inconsistent way, can be enough to confuse the user, and ruin their experience while visiting the application.

Consistency is key

An inconsistent experience can render the whole application useless.

State Management

A sync'd state is essential to preserve a good user experience across decoupled frontends. You can refer to the pros and cons page, to understand why state is very important.

Event-driven patterns and middleware can help propagate state across decoupled components, even when independently deployed, or deployed hrizontally at scale.

Pub/Sub

A publication and subscription bus is a a good strategy to manage state, and it can be implemented at an infrastructure level, with serverless functions, or client-side, leveraging the browser's addEventListener API and windows.postMessage(), to communicate events across frontend components.

pub/sub

image caption: publication and subscription bus

Persisting state

Although not everybody will agree on this statement, I am one of those system architects that believes state should be almost exclusively persisted at a database level, and that when you need client-side persistence, we should be using one of the many options -cookies, localStorage or IndexDB, depending on the case, but only as a proxy to a database in origin.

Preserving runtime performance

Although the practices described below are considered to be best practices for any web application's frontend, regardless if it qualifies as micro-frontend or decoupled frontend or not, it is important to understand that optimizing runtime performance may be especially challenging in this context and that the recommendations below are to be considered.

Architecting for the user (experience)

Architecting a decoupled system with the user in mind, implies specifying from the use-case or user story, in a way that we can effectively decompose the system into smaller parts, connected by an API-first data distribution system.

An in-depth analysis and understanding of the user's needs, and the business goals, will help us to identify the right level of granularity and decoupling needed, as well as what technologies, mechanisms and processes that are better adjusted to solve each specific use-case problems.

Please go to theframeworks section to learn more about tech-stack options, mapping to different micro-frontend patterns.

user case based architecture

image caption: architecting for the user

usecases

image caption: decoupled applications examplesx

Know your user

  • User diversity

    Users that will interact with your application have different abilities and needs. This is why it is very importat to cater for those, by implementing user-experience and accessibility best practices.

  • Global userbase

    A global user-base implies your application will be downloaded and used by people in different geolocations, and therefore, with different network conditions. This is why it is important to optimize your code and your architecture, to reduce latency and throughput related performance degradation.

  • Device capacity

    Not only the network speed may differ, but the devices our users employ to intract with our user interfaces or frontend, may be very different to the ones we use at development time and to test our apps. At the time of writing this website's info, end of 2022, only 28% of the world's population use an iPhone (16% in LATAM and 14% in APAC). Most users' will browse your app from a USD 200 baseline smartphone.

    You can learn more visiting Alex Russell's blogsite, where he has a lot of data backed-up information about the device gap.

Know the benchmarks

  • Critical path budget

    The critical path (or render-blocking path) defines the resources that must be sequentially downloaded to correctly render a webpage. For a USD 200 smartphone, the critical path budget should be approximately 150 Kbs. Read more...

  • Bounce rate

    The bounce rate represents the percentage of visitors that wil abandon a user-experience after a certain amount of time, when they're not satisfied with it because it is slow, irresponsive or not meeting their expectations.

    The bounce rate is about 32% for mobile devices taking between 1 and 3 seconds to load content, and 90% for sites that take between 1 and 5 seconds, to load content.

    Read more...
  • Request assets count and size

    Another important metric to determine we're implementing good practices with performance and the end-user in mind, is to limit the asset count to 50, and and keep the total size of the assets in one page, to under 3MB. That means the total size of static assets like images, fonts, videos, etc.

    Read more...

Performance recommendations

  • Use next generation frameworks

    Next generation frameworks are built with both performance and DX in mind; they equip developers with out of the box tools and mechanisms to optimize your decoupled frontends.

    Go here to learn more..

  • Stick to web platform APIs and standards

    Avoid 3rd party dependencies, when possible. Ship less JavaScript by leveraging APIs available in the browser and implementing progressive enhancement.

  • Lazy load everything

    Async or defer load using dynamic imports, HTML loading attributes or any suitable technique.

  • Optimize your code

    Tree-shake, bundle, minimize, compress and eliminate dead code.

  • Define a performance budget

    Enforce and respect the definition. It should not change or grow with your app size.

Move all possible compute and composition to the cloud

Move all critical and CPU intensive compute to the cloud, leveraging the multiple advantages of fully-managed serverless and cloud native infrastructure

Learn more..

I was recently asked more about this statement in social media..."Why would we want to move computing to the cloud when we relatively have a lot of computing power in the browser, for free?"

The answer is in the question. We have a lot of computing power in the browser, for free. But it's not free. It's free for the browser, but not for the user.

When we design frontend applications that may need to perform heavy computations, we need to understand there is no reliable way to know any of these things:

  • What is the device's actual capacity
  • What is the browser's actual capacity
  • What is the connection speed
  • And for those transactional computations that may be requestion more data, and needing a response to continue, what the latency will be

We may be able to reasonably get that information at runtime, but given 3 users A, B, and C, we can expect that the actual capacity is different for each one of them.

This is why practicing progressive enhancement, is a good way to ensure a good user experience for each one of them.

Coming up!

Validating user flow with e2e testing