avatarIgor Katsuba

Summary

The article discusses the implementation of a layered architecture in a micro-frontend CRM application, detailing the structure, dependency rules, and benefits of this approach.

Abstract

The third part of a series on micro-frontend architecture, this article delves into the practical application of a layered architecture within a CRM system. It outlines the various layers, including Core, Features, Blocks, Pages/Tasks, and Application, and emphasizes the importance of dependency constraints between these layers. The layered approach is credited with enhancing modularity, reusability, maintainability, scalability, and ease of onboarding for new developers. By adhering to strict rules and utilizing tools like Nx and linting within a monorepo, the team manages to maintain high code quality and align with the principles of layered design. The article concludes by teasing the next installment, which will cover the tools and practices that support this architecture.

Opinions

  • The author advocates for the use of layered architecture in micro-frontends, suggesting it leads to better-organized code and easier maintenance.
  • Inspiration for their layered architecture was drawn from Nx and Feature-Sliced Design (FSD), though they adapted the concept to fit their needs.
  • The article expresses a preference for clear separation of duties and structured dependency rules to prevent tangled code dependencies.
  • The team values the use of a monorepo for managing multiple micro-frontends, with each product having its own scope.
  • Shared scopes are treated with caution, requiring full consent from code owners due to their common status.
  • The author believes that the layered architecture significantly contributes to the project's success, citing specific advantages like modularity and improved scalability.
  • There is an emphasis on the importance of tools and automation in maintaining code quality standards within the layered architecture.

Micro-frontend Architecture. Part 3. Layered Architecture

Hello everyone! Welcome to the third part of our journey into micro-frontend architecture. After delving into architectural decisions and the technical stack, it’s time to explore layered architecture in practice, using our CRM application as an example.

What is Layered Architecture?

Layered architecture is a development approach that suggests dividing an application into multiple layers. These layers are usually organized by responsibility and interaction with other layers, facilitating a clear separation of duties and simplifying code maintenance. Typically, layers have dependency constraints to prevent tangled code dependencies.

For instance, Nx offers layered architecture through different types of libraries within a single monorepo: feature, UI, data-access library, and utils. However, the official documentation does not specify any restrictions or rules for these layers. Therefore, we were inspired by another example of layered architecture — FSD. We adopted only the concept of layers and their interrelations, while FSD offers a deeper separation, which you can read about in its documentation.

Layers

Let’s take a look at the layers we identified in our CRM:

  • Core layer — a set of “dumb” components, services, directives, and utility functions that can be used anywhere in the application and beyond.
  • Features — features are responsible for business logic and interaction with the API.
  • Blocks — a composition of features responsible for data display and user interaction.
  • Pages or tasks — application pages or CRM tasks, which handle internal routing and feature composition.
  • Application layer — the main application component responsible for configurations and initial routing.

It’s worth mentioning that we work within a monorepo that can contain more than one micro frontend. Each micro-frontend is a product, with a specific team responsible for one or several such products. To separate products, we identified scopes, usually correlating one scope per product.

Dependency Constraints

I listed the layers from the bottom up and ended with the application layer for a reason. This order helps trace dependencies between them. Each higher layer can depend only on the one below it. Thus, the feature layer can depend only on blocks, the application layer on pages, etc. Dependencies within the same layer are also not allowed, except for the core layer. Any layer can depend on the core, and core components can depend on other core components.

It’s important to remember scopes. A scope encompasses all dependency branches of a product. If these branches intersect, the intersections should attain a shared scope status. Creating shared scopes is only done with the full consent of the code owners, as the “shared” status automatically makes the entire branch common.

Advantages of Layered Architecture

Modularity and Reusability. Layered architecture facilitates the separation of functionality into distinct components, easing code reuse. This allows developers to create independent modules that can be reused in different parts of the application or other products.

Simplified Maintenance and Expansion. Dividing the application into layers makes the code more structured and understandable, simplifying maintenance and adding new functionality, as developers can easily locate and modify relevant parts of the application without affecting the rest of the code.

Improved Scalability. The clear separation of responsibilities among different layers makes the application more scalable.

Faster Onboarding for New Developers. Due to strict rules, the project structure never changes. Developers can quickly understand which components perform which functions and how they interact with each other.

Summary🌟

Adopting layered architecture in our project has brought us significant advantages: modularity, simplified maintenance and expansion, improved scalability, and faster onboarding of new developers. Dependency constraints between layers and within scopes ensure clarity and order in the project structure, allowing us to manage product complexity and quality effectively.

What’s Next?

In the next part, we’ll take a closer look at the tools and practices we use to align our architecture with the principles of layered design. We’ll show how Nx helps us manage dependencies between layers, how we use linting to maintain order in the monorepo, and how automation helps us maintain a high code quality standard. Join us to learn more about the technical aspects of implementing layered architecture in a large-scale project!

✨ Missed my earlier articles? ✨

No worries, here are the links to the past installments in our series:

🔗 Be sure to catch up to get a comprehensive understanding of micro-frontend architecture and how we are integrating it into our systems. Stay tuned for more insights and in-depth discussions! 🚀

Micro Frontends
Web Development
Angular
Layered Architecture
Monorepo
Recommended from ReadMedium