
Ask HN: What do you use to build micro-front ends? - pscanf
Micro-frontends have been recently listed in Thoughtworks Technology Radar as
&quot;a technique to assess&quot;[0]. They describe it as an approach parallel to the
microservices pattern seen on the backend: a monolith front-end web app is
broken into many sub-applications, each with a certain level of independence
from the others so that it can be developed, tested and deployed in isolation.
These sub-applications share a set of primitives to allow for a cohesive user
experience.<p>Spotify desktop client is reported[1][2] to be built with such an approach,
isolating micro-apps into iframes using libraries and postMessage APIs to
coordinate. I&#x27;ve personally run into an application built in a similar way,
where many iframes shared APIs exposed by their parent window.<p>I was wondering if someone in the HN crowd had experiences &#x2F; tools &#x2F; frameworks
to share to help someone looking into this topic.<p>Thanks :)<p>[0] https:&#x2F;&#x2F;www.thoughtworks.com&#x2F;radar&#x2F;techniques&#x2F;micro-frontends<p>[1] https:&#x2F;&#x2F;www.quora.com&#x2F;What-is-the-technology-stack-behind-the-Spotify-web-client&#x2F;answer&#x2F;Andreas-Blixt<p>[2] https:&#x2F;&#x2F;www.quora.com&#x2F;How-is-Javascript-used-within-the-Spotify-desktop-application&#x2F;answer&#x2F;Mattias-Petter-Johansson
======
itamarst
[https://www.mosaic9.org/](https://www.mosaic9.org/) from Zalando. Here's a
talk they gave about it: [https://www.microservices.com/talks/mosaic-
microservices-zal...](https://www.microservices.com/talks/mosaic-
microservices-zalando-tech/)

------
nevon
We're doing something like that for Klarna Checkout
([https://www.klarna.com/us/business/sell-online-with-
klarna](https://www.klarna.com/us/business/sell-online-with-klarna)). At
first, we built applications as completely standalone applications that were
loaded into iframes and communicated over postmessage. We're still doing that
for some things, but it has some big drawbacks, especially when it comes to
bundle size and browser support. Bundle size is pretty obvious, since you end
up sending the same libraries multiple times, and since the applications are
separated, you can't extract common dependencies at build time. As for browser
support, you basically cannot nest more than two levels of iframes (parent ->
iframe -> iframe), or all hell breaks loose. If any nested frame needs to be
able to scroll or has form fields, prepare for pain.

What we're testing out now is distributing the "applications" as blackbox
React components which are built into the consuming applications. The state of
the applications is contained completely within the component, and the API is
just exposed through props. It increases the coupling between applications,
since it forces everyone to use React and even be on more or less the same
version of React, but that was already the case for us, so it seems like an
okay tradeoff. One downside is obviously that the consuming application grows
larger and larger as we add applications to it, but that can probably be
solved by asynchronously loading chunks on demand.

------
bgrohman
Multiple Angular SPAs that live at different URLs (e.g. one at /admin, one at
/foo, etc). The apps use shared Bower components as needed for common
functionality such as the navigation components. Clicking on a nav link from
/admin to /foo is actually a full page refresh that loads a different Angular
app.

------
mintlysocial
Microservices and Front-End

Microservices are becoming more and more popular and many are choosing to
transition away from monolithic architecture. However, this approach was
mostly limited to back-end services. While it made a lot of sense to split
them into smaller independent pieces that can be accessed only through their
APIs, same did not apply to front-end. Why is that? I think that the answer
lies in technologies we’re using. The way we are developing front-end is not
designed to be split into smaller pieces.

Server-side rendering is becoming history. While enterprise might not agree
with that statement and continues pushing for server-side frameworks that
“magically” transform, for example, Java objects to HTML and JavaScript,
client frameworks will continue to increase in popularity slowly sending
server-side page rendering into oblivion. That leaves us with client-side
frameworks. Single-Page Applications are what we tend to use today. AngularJS,
React, ExtJS, ember.js and others proved to be a next step in evolution of
front-end development. However, Single-Page Applications or not, most of them
are promoting monolithic approach to front-end architecture.

With back-end being split into microservices and front-end being monolithic,
services we are building do not truly adhere to the idea that each should
provide a full functionality. We are supposed to apply vertical decomposition
and build small loosely coupled applications. However, in most cases we’re
missing visual aspect inside those services. All front-end functionalities
(authentication, inventory, shopping cart, etc) are part of a single
application and communicate with back-end (most of the time through HTTP) that
is split into microservices. This approach is a big advancement when compared
with a single monolithic application. By keeping back-end services small,
loosely coupled, designed for single purpose and easy to scale, some of the
problems we had with monoliths become mitigated. While nothing is ideal and
microservices have their own set of problems, finding production bugs,
testing, understanding the code, changing framework or even language,
isolation, responsibility and other things became easier to handle. The price
we had to pay was deployment but that as well was greatly improved with
containers (Docker and Rocket) and the concept of immutable servers.

If we see the benefits microservices are providing with back-end, wouldn’t it
be a step forward if we could apply those benefits to front-end as well and
design microservices to be complete with not only back-end logic but also
visual parts of our applications? Wouldn’t it be beneficial if a developer or
a team could fully develop a feature and let someone else just import it to
the application? If we could do business in that way, front-end (SPA or not)
would be reduced to a scaffold that is in charge only of routing and deciding
which services to import.

I’m not trying to say that no one is developing microservices in such a way
that both front-end and back-end are part of it. I know that there are
projects that do just that. However, I was not convinced that benefits of
splitting front-end into parts and packing them together with back-end
outweights downsides of such an approach. That is, until I discovered web
components.

Web Components

Web components are a group of standards proposed as a W3C specification. They
allow creation of reusable components that can be imported into Web
applications. They are like widgets that can be imported into any Web page.

They are currently supported in browsers based on WebKit; Chrome, Opera and
FireFox (with manual configuration change). As usual, Microsoft Internet
Explorer is falling behind and does not have them implemented. In cases where
browser does not support web components nativelly, compatibility is
accomplished using JavaScript Polyfills.

web components consist of 4 main elements which can be used separately or all
together:

Custom Elements Shadow DOM HTML Imports HTML Templates Custom Elements

With Custom Elements we can create our own custom HTML tags and elements. Each
element can have its own scripts and CSS styles. The question that might arise
is why do we need Custom Elements when the ability to create custom tags
already exists? For a long time now we can create our own tags, apply CSS
styles and add behaviors through scripts. If, for example, we would like to
create a list of books, both with Custom Elements and custom tags we would end
up with something like following.

1 <books-list></books-list> What web components bring to the table are, among
other things, lifecycle callbacks. They allow us to define behaviors specific
to the component we’re developing.

We can use the following lifecycle callbacks with Custom Elements:

createdCallback defines behavior that occurs when the component is registered.
attachedCallback defines behavior that occurs when the component is inserted
into the DOM. detachedCallback defines behavior that occurs when the element
is removed from the DOM. attributeChangedCallback defines behavior that occurs
when an attribute of the element is added, changed, or removed Shadow DOM

Shadow DOM allows us to encapsulate JavaScript, CSS and HTML inside a Web
Component. When inside a component, those things are separated from the DOM of
the main document. In a way, this separation is similar to the one we’re using
when building API services. Consumer of an API service does not know nor cares
of its internals. The only thing that matters for a consumer are the API
requests it can make. Such a service does not have access to the “outside
world” except to make requests to APIs of other services. Similar features can
be observed in web components. Their internal behavior cannot be accessed from
outside (except when allowed by design) nor can they affect the DOM document
they reside in. Main way of communication between web components is by firing
events.

HTML Imports

HTML Imports are the packaging mechanism for web components. They are the way
to tell DOM the location of a Web Component. In context of microservices,
import can be a remote location of a service that contains the component we
want to use.

1 <link rel="import" href="/services/books/books-list.html"> HTML Templates

The HTML template element can be used to hold client-side content that will
not be rendered when a page is loaded. It can be, however, instantiated
through JavaScript. It is a fragment of code that can be used in the document.

Microservices With Front-End

Web components provide a very elegant way to create pieces of front-end that
can be imported into Web applications. Those pieces can be packaged into
microservices together with back-end. That way, services we are building can
be complete with both logic and visual representation packed together. If this
approach is taken, front-end applications can be reduced to routing, making
decisions which set of components to display and orchestration of events
between different web components.

Now that we are equipped with (very) basic information about web components
and desire to try a new approach to develop microservices, we can start
building a microservice with both front-end and back-end included.

In the Developing Front-End Microservices With Polymer Web Components And
Test-Driven Development series we’ll explore one of the ways to put discussion
from this article into practice. We’ll use Polymer, Google library for
creating web components, Docker, Docker Compose and few more tools and
libraries. Development will be done using test-driven development (TDD)
approach.

