Avatar of Till Schulte-Coerne

Dieser Artikel ist auch auf Deutsch verfügbar

System boundaries tend to be a nuisance from the user’s point of view. Thus the motivation for the modularization of systems is purely technical and should not hinder of frictionless workflows without any major loss of context.

So if we have cut up our systems “for reasons”, we have to bring them together in the frontend for our users. This can happen at different points:

  1. Static overarching things like layouts can be integrated during the build or deployment.
  2. With dynamic content, the backend can obtain necessary information from other systems. This can mean making direct calls to another system to process the request in question. In this case, a response from another system is needed in order to answer your own request. This could also mean asynchronous interactions between servers that are decoupled from the request/response cycle, such as a feed-based replication of data.
  3. From the author’s point of view, however, the silver bullet is integration in the frontend, specifically in the user’s browser. This type of integration is usually more lightweight, has better performance and has the fundamental advantage that our own systems (i.e. the backends) do not have to wait for another system (resulting in a delay in our own response) because the integration takes place on the user’s end device.
Figure 1: The problem with integrating multiple backends
Figure 1: The problem with integrating multiple backends

Much has already been said about the first two options, so this article will address the third option: frontend integration. As so often happens in IT, there is not only one option for implemeting frontend integration, but many. The following sections provide a list of some of the options (disclaimer: the list does not attempt to be exhaustive).

The list should begin with today’s quasi-standard. This is the monolithic single-page app (SPA) written in the frontend framework that was trending during the year that the app was created.

Monolithic SPA

In my opinion, the ongoing microservices hype was primarily a hype in the backend. This means that many microservice architectures arose without consideration for anything apart from the backend. If you then find time to deal with the “little problem” of the frontend, and take the simultaneous hype for single-page apps at face value, it seems logical to integrate the backends at the level of your APIs.

A Single Page App (SPA) is then built, typically with a special team of UI/SPA experts. Normally, this app will make Ajax calls to the REST APIs of the backend team.

What is convincing about this concept is that the web frontend is a completely independent system. It therefore fits in seamlessly with other consumer systems like the mobile client for iOS or the calls to a partner company, as any architect would wish when drawing it on paper or a flipchart.

Figure 2: Integration in monolithic SPA
Figure 2: Integration in monolithic SPA

Unfortunately, a closer look reveals some technical problems:

  1. Public APIs must all have cross-cutting issues such as authentication or security in general. However, this can usually be solved somehow with infrastructure.
  2. The naive approach to the orchestration of service calls against different backends over the internet is the opposite of highly performant. This is especially the case when it comes to mobile internet. Here there are no simple technical solutions, only architectural ones: The backend-for-frontend pattern helps out if the frontend team is allowed to build a backend system (typically using NodeJS). This special backend system takes over the orchestration of the actual backends and can thus be considerably more compact and communicate more efficiently with the frontend.

However, the main problem with this approach is not technical but rather one of organization: by having invented a cross-sectional frontend team, the fundamental idea of microservices is actually being violated. Ideally, microservices should customize teams and systems around business areas, which can never be the case with a cross-sectional team (otherwise it wouldn’t be a cross-sectional team).

As a consequence, it is difficult to imagine that a new feature could be implemented by one team alone. As a rule, each new functionality in the backend will require a corresponding feature in the frontend, and vice versa, in order for it to be usable at all.

Pros:
Cons:

Modular SPA

However, the organizational problem of a monolithic SPA can be addressed with technical means and some effort. To do this, the SPA is divided into several modules that are provided by the respective specialized teams. This means that there is still one Single Page App in exactly one framework version. However, this app optimally loads its functionality in the form of modules directly from the different systems and integrates them via framework-specific interfaces.

One option for executing this approach is Angular lazy Feature modules. In this case, the components of an application are distributed in various so-called Feature Modules and are loaded only when they are needed. It is also possible to load these modules from different sources. This mechanism can be used to load the feature modules from different backends only at runtime on the client. With a proper module interface, the teams then regain sovereignty over their functionality and are able to develop and roll out new features independently and wholly in the spirit of microservices.

With webpack-based projects, this can also be done via Lazy Loading. In principle, every modern module bundler and every modern SPA framework contains some mechanism for this. For example, this is the fundamental idea of the Polymer framework.

Figure 3: SPA modules are loaded by different backends
Figure 3: SPA modules are loaded by different backends
Pros:
Cons:

“Flat” SPA

To make sure that a monolithic single-page app does not become too large, is is possible to try to keep the feature set of the SPA as small as possible. For example, an SPA for a dashboard could be built by an appropriate dashboard team and make use of the JSON backend APIs of the other systems. This SPA should then be as “flat” as possible, i.e., it should jump as quickly as possible into the frontend of the respective responsible system.

Figure 4: A flat SPA branches quickly into the subsystems
Figure 4: A flat SPA branches quickly into the subsystems
Pros:
Cons:

Complex technical DOM components

Single-page approaches usually take control over the entire site. But consider what would happen if JavaScript was used for developing complex frontend components, and these were completely independent, i.e., without the requirement for a “framework” or the routing around it? So what would happen if we do not build an app, as is common on the web, but still want to execute a high level of technical logic on the client side?

The Web Components Standard CustomElements would be suitable for this. With this standard, components can be defined that initialize themselves on the DOM without needing a framework. Such a component could then, for example, load data from the backend JSON APIs, manipulate the DOM, send events to other components, etcetera …

In the simplest case, these components are instantiated by server-side HTML. The individual backend systems can simply serve HTML and integrate its own components as well as the components from other systems by referencing them in their own HTML.

Figure 5: Complex components are integrated via the DOM
Figure 5: Complex components are integrated via the DOM

Components of this type can also be built using SPA technologies such as Angular, vue or React. However, this is only worthwhile if they still load quickly and do not have a very large “footprint”. In addition, modern SPA frameworks such as Angular are unfortunately not built with this in mind and often take control over the entire site, or, at the very least, the URL.

Other frameworks like Polymer or Stencil are actually built with this idea in mind. However, the decision of which framework to use will be strongly influenced by the size of the respective components, at least for public sites. In the case of Polymer, these can be in the three-digit kilobyte range when unzipped.

Pros:
Cons:

Links

By comparing the “complex technical components” approach to the SPA approaches, an important step has been made: We are integrating the backend systems, at least potentially, via HTML rendered on the server side. If all backends provide most of their functionality via server-side HTML, this makes a much simpler method of integration possible: the hyperlink.

If you want to integrate the functionality of another system into your respective system, you can just link it. The user thus switches to the other system and simply returns to the first one upon finishing their work there. If the look and feel of the target system is the same, the user will not even notice that there was a switch in the system. Of course, it is important that the link points sufficiently “deeply” into the target system so that the user goes directly to the place where it is possible for them to continue working.

Figure 6: Links hand over the user flow to another system
Figure 6: Links hand over the user flow to another system

However, the interesting question here is exactly where the user should be directed back to. A naive response may be permanently configured “entry points” in each application. However, this would probably not support the workflow of the user, as the user would first have to restore their context in the system upon return.

For this purpose, it is better to integrate a special parameter that all systems must know and handle correctly in the URIs and forms. This parameter usually contains the return URI to which one should “redirect” back to after successful execution of the sub-process in the original system.

Figure 7: Return URIs enable a seamless return to the original system after the work has been completed without having to rebuild the context
Figure 7: Return URIs enable a seamless return to the original system after the work has been completed without having to rebuild the context

The following questions must also be answered in the respective architecture:

Pros:
Cons:

Hypermedia with data transfer

If you want to solve the not-entirely-solvable problem of data transfer between systems via frontend, you can use HTML forms for this purpose. A backend can thus wrap data that it wants to transfer to another backend into a form that “points” to the other backend. If the user submits this form, the system change is completed and the target system receives the data.

Data that the user should not be able to manipulate, such as IDs or internal URIs, could be embedded in hidden fields within such forms. However, it must then be ensured that this data cannot be modified by the user, since they can be changed as desired in the browser before being sent, for example, in the developer tools. Therefore, a signature must also be added into the form on the server side and validated on the target system.

Figure 8: The system of origin embeds its data in `hidden fields` and signs it for the target system
Figure 8: The system of origin embeds its data in hidden fields and signs it for the target system

If such a form consists exclusively of hidden fields, i.e., no additional data input by the user takes place, links can be used for this procedure again and the information can be packaged in corresponding URI parameters. Here it is still necessary to check the integrity of the data here as well, for example, via signatures. This process is often found in procedures for exchanging tokens for single sign-on solutions.

If the user is not even allowed to know the content which is to be transmitted, the confidentiality of the data must also be ensured. For this, encrypted data must be stored in the forms or links.

Pros:
Cons:

Client-side transclusion

If simple links are not sufficient, you could try to integrate the functionality of other systems in the by integrating toher HTML into your own HTML. This is often called client-side transclusion.

Using small generic JavaSciprt snippets in the browser, content is loaded from other systems into its “own” (usually rendered by the server) DOM. Conceptually, a link to an external system is replaced with the content of the response when executing an HTTP GET on this link.

Figure 9: Transclusion looks similar to complex components but integrates HTML instead of JavaScript components
Figure 9: Transclusion looks similar to complex components but integrates HTML instead of JavaScript components

As simple as the concept is to implement technically, many questions remain unanswered. To display any HTML content usually requires CSS and JavaScript resources; the bare HTML is not sufficient. Is it possible that the systems which will provide the HTML to be embedded can expect that all CSS or JavaScript is already present within the embedding system? Or should there be a mechanism by which the embedded system obtains CSS and JavaScript in the browser?

After some consideration of the existing requirements, these questions can usually be answered relatively quickly (see references).

Pros:
Cons:

Other links:

IFrames

The main complexity of transclusion arises from the fact that one throws HTML content from different sources into a common DOM without any isolation. In order to avoid this, there is a solution provided by the HTML standard: IFrames. IFrames embed a completely self-contained browser view within another browser window. CSS and, especially, JavaScript are isolated from each other and have their own resources.

Figure 10: IFrames represent the highest form of isolation of content embedded on one page
Figure 10: IFrames represent the highest form of isolation of content embedded on one page

The use of IFrames when embedding “foreign” content is actually standard on the World Wide Web. For example, embedded Google Maps are initialized with a JavaScript call in the embedding browser window. However, the call immediately opens an IFrame where everything else takes place.

Using the standardized “postMessage” method, IFrames can exchange messages with other IFrames or in the embedding window.

Pros:
Cons:

Conclusion

Many roads lead to Rome, none of which are trivial, and there is not one that is automatically correct. As is standard in IT, the one that you choose in the end is always the wrong one. To select more than one way, if possible, is not the worst idea.

The author expects the most from the complex technical components. Integration via the standard mechinism CustomElements appears to be relatively optimal, as this leaves it open as to whether the component is initialized by server-side HTML or by another component. It also enables building modern maintainable UIs without getting stuck in the dead end of a single SPA framework.

Contact us