DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • The Power of @ngrx/signalstore: A Deep Dive Into Task Management
  • Micro Frontends Architecture
  • React, Angular, and Vue.js: What’s the Technical Difference?
  • What Is API-First?

Trending

  • Doris: Unifying SQL Dialects for a Seamless Data Query Ecosystem
  • How to Configure and Customize the Go SDK for Azure Cosmos DB
  • GDPR Compliance With .NET: Securing Data the Right Way
  • My LLM Journey as a Software Engineer Exploring a New Domain
  1. DZone
  2. Data Engineering
  3. Data
  4. Angular Libraries and Microservices

Angular Libraries and Microservices

Check out how to implement microservices on the front-end with client-side UI patterns and Angular libraries.

By 
Antonio Goncalves user avatar
Antonio Goncalves
·
Dec. 18, 18 · Analysis
Likes (4)
Comment
Save
Tweet
Share
38.7K Views

Join the DZone community and get the full member experience.

Join For Free

This article is featured in the new DZone Guide to Microservices. Get your free copy for insightful articles, industry stats, and more!

We live in a microservices world, and this world is here to stay. Back-end developers need to dive into Domain-Driven Design, write stateless, resilient, highly available services, keep data synchronized through Change Data Capture, handle network failure, deal with authentication, authorization, JWT... and expose a beautiful Hypermedia API so the front-end developers can add a great user interface to it.

Good! But what about the front-end?

Let's say we have several microservices, several teams, several APIs and, therefore, several user interfaces. How can you create an integrated and consistent user interface so your users don't actually see that there are as many user interfaces as there are Microservices? In this post, I'm implementing the client-side UI composition design pattern using Angular Libraries.

A Microservices Architecture

Let's say we have a CD BookStore application that allows customers to buy CDs and books online, as well as administrators to check the inventory. We also have a complex ISBN number generator to deal with. If we model this application into microservices, we might end up splitting it into 3 separate microservices:

  • Store: Deals with displaying information on CDs and books, allows users to buy them.

  • Inventory: Allows administrators to check the availability of an item in the warehouse and buy new items if needed.

  • Generator: Generates ISBN numbers each time a new book is created.

We end up with two roles (user and admin) interacting with these 3 APIs through a single user interface:

Image title

Client-side UI composition.

In a perfect world, these three microservices are independent, developed by three different teams and, therefore, have three different user interfaces, each released at its own pace. On one hand, we have three different UIs, and on the other, we want our users to navigate into what they see as a single and integrated application. There are several ways of doing it, and one way I'm describing here is called the Client-side UI composition design pattern:

Problem: How to implement a UI screen or page that displays data from multiple services?

Solution: Each team develops a client-side UI component, such an Angular component, that implements the region of the page/screen for their service. A UI team is responsible for implementing the page skeletons that build pages/screens by composing multiple, service-specific UI components. The idea is to aggregate, on the client side, our three user interfaces into a single one and end up with something that looks like this:

Image title

Aggregating several UIs into a single one works better if they use compatible technologies, of course. In this example, I am using Angular and only Angular to create the 3 user-interfaces and the page skeleton. Of course, Web Components would be a perfect fit for this use case, but that's not the purpose of this article.

Angular Libraries

One novelty with Angular CLI 6 is the ability to easily create libraries. Coming back to our architecture, we could say the page skeleton is the Angular application (the CDBookStore application), and then, each microservice user interface is a library (Store, Inventory, Generator).

In terms of Angular CLI commands, this is what we have:

# Main app called CDBookStore
$ ng new cdbookstore --directory cdbookstore
/
  -routing
true
# The 3 libraries for our 3 microservices UI
$ ng generate library store --prefix str
$ ng generate library inventory --prefix inv
$ ng generate library generator --prefix gen

Image title

Once you've executed these commands, you will get the following directory structure:

  • src/app/ is the good old Angular structure. In this directory, we will have the page skeleton of the CDBookStore application. As you will see, this skeleton page is only a sidebar to navigate from one Microservice UI to another.

  • projects/ is the directory where all the libraries end up

  • projects/generator: the UI for the Generator microservice.

  • projects/inventory: the UI for the Inventory microservice.

  • projects/store: the UI for the Store microservice.

The Skeleton Page

The skeleton page is there to aggregate all the other components. Basically, it's only a sidebar menu (allowing us to navigate from one Microservice UI to another) and a <router-outlet>. It is where you could have login/logout and other user preferences. It looks like this:

Image title

In terms of code, despite using Bootstrap, there is nothing special. What's interesting is the way the routes are defined. The AppRouting Module only defines the routes of the main application (here, the Home and About menus).

const routes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'home', component: HomeComponent},
  {path: 'about', component: AboutComponent},
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

In the HTML side of the side menu bar, we can find the navigation directive and the router:

<ul class="list-unstyled components">
  <li>
  <a [routerLink]="['/home']">
  <i class="fas fa-home"></i>
  Home
  </a>
  <a [routerLink]="['/str']">
  <i class="fas fa-store"></i>
  Store
  </a>
  <a [routerLink]="['/inv']">
  <i class="fas fa-chart-bar"></i>
  Inventory
  </a>
  <a [routerLink]="['/gen']">
  <i class="fas fa-cogs"></i>
  Generator
  </a>
  </li>
</ul>
<!-- Page Content -->
<div id="content">
  <router-outlet></router-outlet>
</div>

As you can see in the code above, the routerLink directive is used to navigate to the main app components as well as library components. The trick here is that /home is defined in the routing module, but not /str, /inv or /gen. These routes are defined in the libraries themselves.

Disclaimer: I am a terrible web designer/developer. If someone reading this post knows about jQuery and Angular and want to give me a hand, I would love to have the sidebar be collapsible. I even created an issue for you!

The Libraries

Now when we click on Store, Inventory, or Generator, we want the router to navigate to the library's components:

Image title

Notice the parent/child relationship between routers. In the image above, the red router-outlet is the parent and belongs to the main app. The green router-outlet is the child and belongs to the library. Notice that in the store-routing.module.ts, we use str as the main path, and all the other paths are children (using the children keyword):

const routes: Routes = [
  {
  path: 'str', component: StoreComponent,
children:
[
  {path: '', component: HomeComponent},
  {path: 'home', component: HomeComponent},
  {path: 'book-list', component:
BookListComponent},
  {path: 'book-detail', component:
BookDetailComponent},
  ]
  },
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class StoreRoutingModule {
}

The beauty of having a parent/child router relationship is that you can benefit from "feature" navigation. This means that if you navigate to /home or /about, you stay in the main application, but if you navigate to /str, /str/home, /str/booklist or /str/book-detail, you navigate to the Store library. You can even do lazy loading on a per feature based (only load the Store library if needed).

Image title

The Store library has a navigation bar at the top, therefore, it needs the routerLink directive. Notice that we only need to use the child path [routerLink]="['book-list']" without having to specify /str (no need to [routerLink]="['/str/book-list']"):

<nav>
  <div class="collapse navbar-collapse">
  <ul class="navbar-nav mr-auto">
  <li class="nav-item dropdown">
  <a class="nav-link dropdown-toggle">Items</a>
  <div class="dropdown-menu" aria-labelledby=
"navbarDropdownMenuLink">
  <a class="dropdown-item"
[routerLink]="['book-list']">Books</a>
  <a class="dropdown-item"
[routerLink]="['cd-list']">CDs</a>
  <a class="dropdown-item"
[routerLink]="['dvd-list']">DVDs</a>
  </div>
  </li>
  </ul>
  </div>
</nav>
<!-- Page Content -->
<div id="content">
  <router-outlet></router-outlet>
</div>

Pros and Cons

The Client-side UI composition design pattern has some pros and cons. If you already have existing user-interfaces per microservices, and if each one is using totally different technologies (Angular vs React vs Vue.JS vs ...) or different framework versions (Bootstrap 2 vs Bootstrap 4), then aggregating them might be tricky and you might have to rewrite bits and pieces to have them compatible.

But this can actually be beneficial. If you don't have extended teams with hundreds of developers, you might end up being the one moving from one team to another one and will be happy to find (more or less) the same technologies. This is defined in the Chassis pattern. And for your end users, the application will have the same look and feel (on mobile phones, laptops, desktops, tablets), which gives a sense of integration.

With the way Angular Libraries are structured, having a monorepo is much easier. Of course, each library can have its own life cycle and be independent, but at the end of the day, it makes it easier to have them on the same repo. I don't know if you love monorepos or not, but some do.

Conclusion

We've been architecting and developing microservices for several decades now (yes, it used to be called distributed systems, or distributed services), so we roughly know how to make them work on the back-end. Now, the challenge is to be able to have a user interface which communicates with several microservices, developed by different teams, and at the same time feels consistent and integrated for the end-user. You might not always have this need (see how Amazon has totally different UIs for its services), but if you do, then the Client-side UI composition design pattern is a good alternative.

If you want to give it a try, download the code, install and run it (there is only the front-end, no back-end APIs). And don't forget to give me some feedback. I would be interested to know what you do to aggregate several user-interfaces into "a single one."

References

  • Building and publishing Angular libraries using Angular CLI

  • How to build a library for Angular apps

  • Building an Angular Library with the Angular CLI (version 6)

  • Building an Angular Library

  • Angular Routing

  • Client-side UI composition pattern

  • NG CLI

  • Bootstrap

  • Bootstrap sidebar

  • Why Google Stores Billions of Lines of Code in a Single Repository

  • You, too, can love the MonoRepo

This article is featured in the new DZone Guide to Microservices. Get your free copy for insightful articles, industry stats, and more!

microservice Library AngularJS

Published at DZone with permission of Antonio Goncalves, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Power of @ngrx/signalstore: A Deep Dive Into Task Management
  • Micro Frontends Architecture
  • React, Angular, and Vue.js: What’s the Technical Difference?
  • What Is API-First?

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!