Modular architecture - how is the frontend of Ergonode built?
From the beginning of the development of Ergonode we wanted to use technologies that allow for maximum flexibility - both on the side of application development and on the side of integration with external tools. The answer to our needs turned out to be microservices architecture.
Although the topic of microservices in applications has been popular for many years, the modular approach to the frontend and separation of its space is a recent trend.
In our case it turned out to be a bull's eye. See why.
Monolith vs microservices
Microservices architecture is used in modern systems and is based on dividing the architecture into smaller components, which in effect build one coherent system. Each module is self-sufficient and pursues a specific business goal. Unlike monolithic architecture, which is based on one indivisible structure, when we want to make a change in a particular service, we work on a specific microservice, rather than working on the code of the entire application.
A microservice architecture is a collection of individual building blocks that can be connected together to form a larger unit. Each such block is a small application with its own architecture and business logic that connects to the rest of the modules. Isolating the business context - that is, the detailed requirements for each area is much easier with this approach.
Of course, a microservices architecture will not always be better than a monolith. Keep in mind that microservices architecture is an additional dimension of complexity to the overall project because it is a distributed systems architecture. The danger, therefore, is too many modules, and thus too many relationships and links between modules, which can obscure the structure of the application.
In the case of Ergonode, however, we wanted to be able to manipulate modules freely - that is, to add more modules or modify existing ones - knowing that this would not cause errors in the whole application.
Monolith
Pros
- less complex architecture
- no additional libraries
- faster response to changes
- less need for specialized knowledge
Cons
- lack of separated business contexts
- inflexible extension
- everyone works on one project
- modifications affect the rest of the application
- more difficult tests
- heavy extensions and code parts replacement
Microservices
Pros
- division into separate business modules
- greater flexibility and control
- separation of work per module
- easier communication with the backend
- Different technologies in the modules
- Possibility of independent implementation of the modules
- tidiness, order and simpler expansion
Cons
- more complex structure
- requires specialized knowledge
- requires additional technology
- sometimes unclear and complicated
Why microservices in Ergonode?
Ergonode is two independent applications, a backend and a frontend, that run independently of each other and connect through API. In such applications, the frontend is often considered as one big, monolithic structure. In our solution we also focused on the microfrontend - obtaining modular architecture also in the frontend was quite a challenge, but in the long run it paid off very well. Another important factor was the need to adapt to the architecture of the backend layer - based on microservices architecture from the very beginning.
Before starting the development work on Ergonode, we set ourselves a number of goals, including business ones, which our application was supposed to meet. They largely gave us the direction of growth.
- First of all, we wanted to build a modular application, so that we can isolate specific business contexts, but also add external modules that will extend the operation of our tool. Ergonode, as an open-source application, gives you the freedom to develop and adapt its operation to specific business needs. We also wanted external contributors to be able to write and add their own modules without interfering with the core application.
- Another assumption was the immutability of the application base - we wanted the core development code of Ergonode to remain unchanged. Of course code customizations happen, but we wanted all modifications to be extensible, not overwritten. If it were possible to interfere externally with the core code, then creating subsequent versions of Ergonode might not be feasible due to conflicts in modules.
- Our goal was to make the implementation of the modules simple - so that the developer who wants to use Ergonode at the client's site could operate on simple deployment mechanisms, could choose the modules that interest him - without having to install all available modules.
- Modules should be versioned, i.e. each module should be separated and have its own release version - upgraded with every new change or update. This provides us with full control and stability for our clients.
- We also made the decision to stay on Vue + Nuxt, since the application was developed on Vue and Nuxt frameworks, we want to continue using these technologies and not add more unnecessary libraries if possible.
Assumptions are one thing, but their execution is not always trouble-free. Modular structure of the frontend based on microservices requires specialized knowledge, which we did not have at the initial stage of work. The experience we gained paid off in the future, but at the beginning we had to spend a lot of time to learn how the libraries work. Along the way it also turned out that the Nuxt.js extension mechanisms alone are not enough. Modifying already existing tools that provide a microservice structure was not an option either.
Therefore, we concluded that having knowledge in Nuxt.js and Vue we would try to write our own solution that would not only solve the problems we encountered, but also fit our needs - without additional technologies and modifications to what we already have. This is how we decided to create our own VueMS (see more about Vue MicroServices) library. It's a simple mechanism to transform a monolithic Nuxt application into one based on microservices architecture.
As with the creation of Ergonode, we had a number of goals that we wanted our library to meet:
- creating a library that modifies the architecture
- preserving the existing mechanisms
- preparation for future development
- flexibility to changes
- support of the library by the Ergonode team
- open source
- openness to suggestions from the community
What is VueMS?
VueMS is based on Vue and Nuxt technologies and retains all the mechanisms they offer - which also means that it is compatible with them. The main task of the library is to transform the monolithic approach of the Nuxt architecture into a modular based one.
Nuxt itself allows mechanisms to be extended through external modules, but our need was more complex. We wanted each module to have a structure similar to a large application, so that its catalog layout and mechanisms would not differ from a large monolithic application. More specifically - each module could have its own pages, its own routing, its own components, plugins and everything that any Vue + Nuxt based application has. A module would not have any restrictions, so it could contain both a huge functionality and a single component or plugin. These mechanisms allow loading modules located locally in the project and modules downloaded from external services such as npm (package manager for the Node.js environment). This allows you to version modules and update them as needed. Packages hosted on npm are thus resistant to modification and only the developers can change and update them. If a base module does not meet the customer's expectations, it can easily be replaced with a custom solution. Communication between particular services was also an important element. We used alias mechanisms, thanks to which communication is simple and very clear. We also have the ability to determine which modules are required and whether the services have relationships with each other.
When creating this library, we wanted it to be open source, just like Ergonode. So we prepared it to be as universal as possible and to be able to support other projects in such architecture modification. We have uploaded it to GitHub and ported it to npm as an installable npm module that can be added to the application as an extension. This gives the possibility to build the application basically from scratch in a microservice architecture approach. The library can also be added to a project that is already running as a monolith, but there is a need to plug in some external modules. VueMS works as a module for Nuxt.js, i.e. it is a package that is installed and dropped into the Nuxt configuration.
Modules in VueMS
Until now, application which was built on Nuxt had a monolithic structure. Starting with the project we had a certain directory structure imposed - with a specific purpose, with components, middleware or plugins thrown in one place. In the approach using our VueMS library, the structure is modified - there is no need to keep everything in one place - we can enclose it in separate modules or business-separated contexts then it will work like a mini application. We have no functional limitations to modules. They can contain huge part of application, they can contain components, middleware, routing, everything what is needed to run application properly, but they can also contain very small part of code, for example only plugin or interface translation.
These modules can be freely separated. In Ergonode - in accordance with microservices architecture - we separated some elements, for which such separation was beneficial - e.g. the core module, which provided us with full mechanics - and contained a pool of elements that other modules could use. In this approach, we found that we would try to separate the core, and isolate the UI module elsewhere - so that it would not have any additional mechanisms. In the VueMS library, we can determine which modules are required and therefore needed for the application to run. When installing the application, the developer chooses which modules he wants to install first. Such freedom in choosing modules may result in the module required for the application to work properly not being installed. In our approach by installing the application we can "dictate" which module is required. Additionally, we have set the relationships between the modules - in the modules' configurations we impose the relationship between another module. For example: in Ergonode the product module has an overriding relationship to the attribute - because it is the product that operates on the attribute, so it needs specific information from the attribute module.
We also provided such mechanisms that facilitate communication between modules - they can reuse certain elements, refer to elements from another component and use them without any problem (if installed).
We've also created support for local and external modules - we're able to install a module that's hosted on disk, and drop in a module that's hosted on npm (or wherever we store packages). When configuring, we can set whether the module is locally downloaded or is externally downloaded - it's downloaded as a typical npm package, and then VueMS reads it and integrates it with the rest.
Local and external modules
The frontend side of Ergonode runs on two repositories - one, has a developer application framework, we have all possible modules in one project - to make it easier for us to implement and develop them. The second repository is the so-called application skeleton, which is installed skeleton for example for customers - it's a skeleton, which does not have any physical module, so the developer who implements the project can not modify them, because they are installed for example with npm and as dependencies thrown into the application. In such a deployment, the developer can use ready-made Ergonode modules, and add their own modules according to the customer needs.
Local module
- development environment
- for contribution
- full interference with the module code
External module
- sub-implementations for the customer
- packages versioning
- no interference with the module, full control
- not only npm (e.g. Verdaccio)
Ergonode powered by the best technologies
The current frontend architecture of Ergonode is the result of a long analysis - technological and business - and the selection of solutions that best meet all needs. The decision to build a microservice frontend paid off in the form of a scalable and easily integrable tool that brings great value to the organization.
Want to see what Ergonode looks like from the inside? Book a demo!