I have built several angular (2+ typescript) applications over the last few years and am quite used to it. However in a project I am getting involved with we are using a micro service architecture which encourages that everything be split into as small usable (and sensible) parts as possible which are later loaded into the main page and can act independently of each other.
If this was a regular HTML page with no interactive content it would be easy to do. But in this case we could have a page with: a search function, a listing function, and a details modal. These things all need to be able to interact with each other and react to events, and preferably act as a SPA, not requiring a page load when you navigate.
In a classical Angular app I would have built this with modules and components (which in turn can use common shared components and all be lazy loaded in) with shared routing set up in a single angular application. But how do I do this while keeping to a micro service standard / architecture?. Is that even desirable for the front end? One could see the modules in Angular as a micro services, but is that good enough?
I have found libraries such as https://single-spa.js.org/. Is this the way to solve this? Creating multiple small apps and sewing them together with another framework above them? This would however require a great deal more bandwidth as the frontend needs to download several things multiple times instead of once.
At first glance this all seems to complicate the task with little benefit. Especially since in a regular Angular app one part of the app could stop working without really impacting another part of an Angular SPA (which is one of the main goals of MS). Are there some standardized metrics one could use to see when its better to create a single SPA or to go with the split up micro service variant?
It's perfectly feasible to use microservices on the back end with a single Angular application on the front end. But if you want to divide it up and it makes sense to do so, you should first look at using multiple modules. You are already using modules (these are added to the imports of your app.
Answer: Yes. All the sites created with Angular are SPAs. AngularJS is defined in the SPA framework.
There are also times when microservices just don't make sense. There may just be no way to split up business logic into a subset of services cleanly without so much functional service coupling that it becomes a monolith. Maybe your application will not be around very long.
Angular modules are serving as the main building blocks. They encapsulate the entire feature, set of components, or a page with its dependencies. It is the perfect option to wrap our micro frontend app into it. The routing feature comes with Angular out of the box and you don't have to install external packages.
Summary
A microservices back end doesn't require a microservices front end. You probably want to organise your angular application by module unless you have an exceptionally large application that would be better as multiple smaller independent applications. In which case, Angular may not be the best framework for you.
You shouldn't choose to architect the frond end application in a certain way just because the server side application is architected like that. It's perfectly feasible to use microservices on the back end with a single Angular application on the front end. But if you want to divide it up and it makes sense to do so, you should first look at using multiple modules.
You are already using modules (these are added to the imports of your app.module file) such as HttpClientModule so it's not a big step to create your own. A module would contain components relating to a part of the application such as a particular feature or a set of UI components.
Modules don't immediately provide any technical benefits but from a developer perspective they help organise large codebases. You can however opt to lazy-load these to speed up the initial load time for the application, and to pre-load the lazy loaded modules so the application will load the other modules after loading the initial page. Initially, you would probably want to keep all the modules in a single codebase which makes managing the code easier. As the application grows you can split the modules into separate repositories if you ever get to the point where that seems like a good idea. They can then be installed with your package manager (NPM) and imported as you would import other third party modules, but you still have one app.
Using this approach you still have the benefits of a Single Page Application but it's more modular. At the extreme end, you could split it out into completely different applications served from different server routes. Which option to choose depends on your requirements but the following may help.
Single Module
Multiple Modules
Multiple Applications
99% of Angular projects should be single applications organised as multiple modules. Given that your question is Angular specific, I've created a simple app with routing, and then split it out over multiple lazy loaded modules so you can compare.
Here's the standard single module app.
Here's a fork of it with exactly the same functionality but split into modules.
I've used feature modules, plus a shared module.
Feature Modules
All the components, directives etc. relating to a feature are contained in the feature module. You can see that the AppModule is much leaner in the multi-module version.
Each module should have its own router (if the feature has routes). All reference to the lazy loaded modules should be removed from AppModule in order to prevent Webpack from including them in the main bundle which would cause them to be loaded immediately. Then, a string representation of the path to the modules can be used to point to the module:
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'places', loadChildren: './places/places.module#PlacesModule' },
{ path: 'products', loadChildren: './products/products.module#ProductsModule' }
]
There are different preloading strategies to determine how lazy loaded modules are loaded. PreloadAllModules will load all lazy loaded modules after loading the initial module.
imports: [
RouterModule.forRoot(appRoutes, { preloadingStrategy: PreloadAllModules })
],
Shared Modules
Shared modules are used to make components directives etc. available to multiple modules. They need to export any of the declarations that will be used by other modules, as well as the CommonModule:
exports: [
CommonModule,
LegalComponent
]
Services
Services can also be provided into individual modules. When provided to lazy loaded modules or shared modules used in lazy loaded modules, you will get a different instance of the service. So to keep the example simple, I've left the services in the AppModule providers array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With