As you may know, AngularJS framework is no longer supported. Creating new pages using that framework is discouraged.
How can we handle existing pages, written with older framework? How can we handle new pages?
There are different strategies that can be used to obtain this goal (at least partially)
- Re-coding from scratch the whole AngularJS application.
- Bootstrap an hybrid application that has both Angular and AngularJS frameworks.
- Keep the older AngularJS as is, freezing it from new-feature-development, and booting an Angular app to be kept side-by-side with the older one, by using the micro frontends paradigma.
Re-coding from scratch the whole AngularJS application
- Easier maintenance: only one framework (Angular).
- Performance improvement for "legacy" part.
- While rewriting the legacy part, you have the possibility to restructure it in a more maintainable way and to write tests for uncovered components/service.
- A lot of time will be needed. No incremental value.
Problem and Solution
When you need a new library or external capabilities, most libraries (Angular wrapper etc.) are now only targeting Angular 2+. Angular offers a series of built-in tools for efficiently migrating AngularJS projects over to the Angular platform, a piece at a time.
One of the keys to a successful upgrade is to do it incrementally, by running the two frameworks side by side in the same application, and porting AngularJS components to Angular one by one. This makes it possible to upgrade even large and complex applications without disrupting other business, because the work can be done collaboratively and spread over a period of time. The upgrade module in Angular has been designed to make incremental upgrading seamless. A detailed guide is on https://angular.io/guide/upgrade.
Built-in APIs offered by Angular are described here: https://angular.io/api/upgrade. They supports the upgrade path from AngularJS to Angular, allowing components from both systems to be used in the same application.
There are different migration strategies, but the most preferred one is to run side by side with Angular being the main application.
- Create Angular application using Angular CLI
- Copy an existing AngularJS app (should be 1.6.x and refactored so that the structure of the code is feature based and each file has a single implementation)
- Migrate JS dependencies (Switch to npm)
- Fix template paths for the legacy AngularJS app, in both JS and HTML
- Migrate css files and fix import paths
- Fix minor CSS issues caused by an introduction of view-container and view-frame
- Regression test (It seems all working at this stage, have a good test by QA)
- Add Angular Routing and introduce a new page
- Switch between AngularJS page and Angular page
- Upgrade can be gradual, even if difficult
- Low regression risk
- Using the upgrade/downgrade Angular functionality, it's possible to use legacy components/services inside Angular app
- "Fast" start but slowness on the mid-long term
- Graphical issues: "legacy" app uses AngularJS and Bootstrap 3. We cannot have on the same page Bootstrap 3 and 4
- Initial loading time of the application could represent a performance issue
- Build issue - built-in ng build from angular CLI does not understand that we are including AngularJS
- The application becomes significantly larger compared to the previous release (4 times larger than AngularJS app)
- Need to apply upgrade/downgrade on existing AngularJS components/services
- If you use UI bootstrap on AngularJS, it seems there is no simple way to have side by side two different versions of Bootstrap
The idea behind Micro Frontends is to think about a website or web app as a composition of features which are owned by independent teams. Each team has a distinct area of business or mission it cares about and specialises in. A team is cross functional and develops its features end-to-end, from database to user interface.
Something often not mentioned in discussions is that micro-frontends can be split horizontally or vertically.
Horizontally would mean the case described here: Multiple independent apps on one view. I really don't want to see the resulting bundle-size for this approach.
Vertical splitting means you have one app for one view, and separate e.g. by subdomain where login.app.com, news.app.com, editor.app.com each have their own app. DAZN works like this, for example.
There is a recommended setup, to boost code performance and bundle size. You also have the possibility to interactively configure the Single SPA entry point, with a playground. A bunch of tutorials and coding examples are available here.
Most interesting features:
- use of multiple frameworks on the same page without refreshing the page,
- lazy load code for improved initial load-time,
- top-level routing.
Here is a Proof of Concept about utilization on the same single page application of multiple (separated) frontend application: https://github.com/Pragmatists/microfrontends
In that POC there is also an example of applications communication, performed by using global events, where data exchange is supported. Also other sharing mechanism are possible.
- Setup of the project should be painless, with the exception of all the initial boilerplate setup
- For the micro-frontend solutions, Single SPA seems like the most mature framework
- There is the possibility to have CSS stylesheets independence by automatically wrapping CSS rules in a namespace dependent on application name (look at https://github.com/ruslansavenok/postcss-wrap)
- Each SPA app can have its own repository and different teams can work w/o conflicts
- Open Points
- Should we deploy applications as independent frontend or bundle everything together? In the first case we need to expose them, for example, in different ports. In the second case, if one - of such application changes, you have to rebuild all together.
- Take care also of file system total size for both solutions, as well as total size of downloaded resources by the user (via the browser)
- In the single bundle approach, is it possible to have conflicting libraries side by side? (e.g. bootstrap 3 and 4)
- How to manage common dependencies?
Working on legacy AngularJS projects, you will soon start to elaborate a migration strategy to a modern framework.
If you are thinking to switch to Angular, React or VueJS, there are different strategies you can follow, depending on both technical and business requirements.
There is an optimum way, that is writing from scratch the entire application. It can be very time-wasting and I am sure that your boss will not easily give you so many time to rewrite something that more or less works, w/o adding any customer value.
Angular’s Upgrade APIs represents a good compromise, that can be leveraged only if you are thinking to migrate to Angular.
The Micro Frontends strategy allow you to create the right abstraction between a specific application implementation, which is highly coupled with a framework, and its functionalities that should be exposed with the outside world. The community, overall, is going in that direction.
The last suggestion that I want to give you is: while you are migrating an application or you are adopting an hybrid approach, why don’t you encapsulate your components/services with Web Component standard? Next time that the framework will change, it will be more easy to perform an upgrade.