As part of the AngularJS series, I’ll be sharing how we migrated two different applications – one using the Strangler Fig Design Pattern, and the other using the Rewrite approach.
The first project took on a front-end application that had hundreds of screens, a considerable number of tests to verify, and new features were constantly introduced. Although the code was well-maintained and of a high-quality standard, these considerations (particularly with respect to code-freeze not being feasible) guided us to follow the incremental upgrade path using the Strangler Fig Design Pattern.
As a quick refresh, this method incrementally upgrades the new application around the edges of the original, letting it grow over time until the original system is eventually completely replaced.
Angular projects such as this, have guidance and support from the language and application environment, providing a stable and proven path to assist with the upgrade (https://angular.io/guide/upgrade). Leveraging built-in tools that can be added to an Angular project to run AngularJS code at the same time, minimises the risk and gives piece of mind while the UI migration is taking place.
Key examples of this are reflected by the fact that an Angular application can load and render AngularJS modules, and vice versa. Angular change detection and AngularJS digest cycle working hand in hand will ensure that all components are not missing any change or encounter out-of-sync variable binding.
Taking the example further and following the documented guidance of the Angular upgrade path, component-based coding offers a structured path to ensuring that AngularJS components can be referred and run in Angular as the upgrade happens piece by piece. The structure of this reflects:
1. In the original AngularJS we should NOT define a route to use a specific controller and html template like in Figure 1.
2. With a Component-based approach, simply register the route with a single component template like in Figure 2.
3. The Controller and the body of the template should be defined by the ModelManagement element directive that we define in Figure 3.
4. Resulting in the new Angular project, referring to and running the AngularJS’s ModelManagement as a component for as long as required.
Other best practices to incorporate into such an upgrade approach include:
With the popularity of task runners such as “gulp” and increasing demands of applying DevOps practices, writing AngularJS application in typescript is already considered a best practice and will assist your upgrade considerably.
These unwritten rules should not be taken lightly when thinking ahead, preparing for a change, and bracing for the disruption in technology. They are part of the preparation work mentioned in the upgrade documentation that set the foundation for the migration work. Make sure to review each preparation step in the documentation so the upgrade process would go smoothly.
Once all preparation tasks were completed, the Upgrade module was added to the project. Refer to Figure 5 for how to use the upgrade module to import/use AngularJS module into Angular app-module.
Then dividing the application into manageable functionality chunks and migrating them directive by directive, controller by controller, module by module.
With a resulting hybrid application like this example, the project manager could always be sure that in each fortnight or sprint, there is always a value-added and the move away from the deprecated original project. Even if the worst-case scenario happens mid-project and a halt is called, there are migrated components and modules in newer Angular that adds value to the business and users.
However, be mindful that this incremental benefit can be a two-edged sword. Without a continued focus on progression and updates, teams could get trapped in not finishing the upgrade and the application remaining in a hybrid mode for longer than they ever need.
Addressing this, removing legacy bugs and security concerns from the production environment as soon as it is feasible is key to a successful Strangler Fig Design pattern approach.
For the second project in this post, the application had around 40 screens and less than 10 modules to rewrite. As the AngularJS was already written in typescript, there were quite a lot of code snippets that could be copied with minimum change into the new Angular project and thus a direct rewrite / cutover was more appropriate.
A key element of a rewrite is the ability for developers to go back and forth between the new and the old versions for comparison as the application was rewritten. To make this straight forward the upgrade setup was importantly designed so that the prebuilt legacy application was served locally in another port as a reference, and then developing the new version to talk to the same API.
As the two projects required different NodeJS and NPM versions to build, the team built the legacy under the old NodeJS version so the distribution assets could be served as a static html/js/css. With some help from nvm (node version manager), the local environment was set to use the latest NodeJS and NPM versions for the new project development setup to work.
Taking 40-50 days of effort, this small-medium sized application was ported into Angular 12.
By using the tooling & techniques such as
this upgrade path was not as difficult as originally thought.
The final product is a lot more robust, maintainable, and follows industry best practices. Coding quality has been improved and performance is a lot better on the new framework.
It now uses modern front-end technologies like redux state management and observables, instead of promises, to manage all the asynchronous tasks in the code.
Some of the benefits from a developer point of view include:
Additionally, Progressive Web Application is easy to set up specifically with Angular 12.
It makes native mobile app customer experience within the reach of the product owner if such capability is desired.
Just like the original AngularJS starter kit that provided us with a seed project to start from, Angular 12 comes with a sleek command line library called Angular CLI to give you a boost in starting a new project. Taking advantage of these CLI commands can greatly reduce development time when generating boilerplate code for new components, services, and modules. It also helps to ensure good coding standards, without little developer input.
Run ‘ng new ` , and voila, the new angular project is created and ready.
Components generated with the `ng generate component ` command, outputs for 4 different files, so each component will have its own dedicated style, unit tests, html template, along with the component’s controller. This way all components are written with a uniformed naming convention and file structure.
Leveraging libraries and using boilerplate templates can be a real productivity booster when it comes to application / UI development. Rolling out tried and tested re-usable code, along with enabling consistency across the code base, lets you achieve better quality outcomes and a faster delivery time.
At Playtime we take template generation further by not only generating a single component for each command. We leverage external open-source libraries to craft our own set of components, service, module, and object models as a single template to generate at once.
As an example, front-end applications would usually have 4 operations to interact with object models from an API. They are create, read, update, and delete (CRUD). We could easily bundle them together, name them consistently and generate the standard components at once.
These templates would refer to our standard toolkit to render table for the list (ng-datatable), pop modal out for delete confirmation (ng-bootstrap), maintain tab state in between URI navigation (ngrx), and form rendering library complete with its validation mechanism for the search and edit component to name a few.
All that’s left is to:
On average, 1 CRUD scenario with its grid view and update form takes our team around 8-12 hours worth of development. Extra effort is required but would be equally beneficial when the object model has a lot more complexity. For example nested attributes, custom components are required for the field, where several show-if logic needs to be implemented for the update form, or a custom endpoint for a specific action is required.
One common attack that is performed against front end applications is Cross Site Scripting (XSS). Although there are guidelines and best practices written to prevent such attacks on an AngularJS application, developers who are not aware of any of these guidelines can be confident coding in newer Angular as levels of protection are already built-in.
The Angular 12 security guide documentation (https://angular.io/guide/security) reinforces that even the basic double curly bracket binding syntax, sanitizes the untrusted value/html template into a safe one thus offering a level of protection against XSS based attacks. Also, interpolation in the innerHTML DOM property is not exempted from this sanitation process (refer to Figure 6).
There are security patches that have been implemented in newer Angular throughout its updates and more are coming including the ones to defend against future attacks. Once the application is upgraded, product owners and stakeholders can breathe easier regarding attacks against critical systems that run the business.
These and many other benefits of having an updated web application brought people to decide which approach they would like to go about upgrading. The waterfall like complete rewrite path, or the less risky yet intimidating approach of incremental enhancement.
Either way with AngularJS LTS expiring at the end of the year, Angular offers better performance, code optimisation, maintainability, and support; it’s never been a more important time to consider your upgrade strategy.
Playtime Solutions has extensive experience in migrating organisations away from AngularJS – from simple to complex legacy applications. Get in touch , and we’ll be more than happy to talk you through the best steps for your organisation.
A 23 page best-practice checklist, leveraging Playtime Solutions’ hands-on experience in designing, developing and delivering enterprise-grade application. This guide assists IT and DevOps professionals in creating an enterprise-grade Kubernetes environment in Microsoft AKS.