Including Front-End Web Components Into Microservices
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.
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 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.
web components consist of 4 main elements which can be used separately or all together:
- Custom Elements
- Shadow DOM
- HTML Imports
- HTML Templates
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.
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
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.
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.
The first article in the series is Developing Front-End Microservices With Polymer Web Components And Test-Driven Development (Part 1/5): The First Component.