Migrating from AngularJS to Angular - A brand new strategy
There are many companies out there that still use the great AngularJS framework, and I do personally think it’s a great front end framework, that has a lot of power, as long as you use it right!
I won’t dive into how to use it right, this is not the purpose of this article, but I write this article for those who’d like to experience and do the next step for the latest Angular framework, but still have millions lines of code.
Who is this article for?
- You’re a company that maintains million lines of code, using AngularJS (1.x)
- You’re required to keep delivering new features to your clients
- You’d like to continue delivering and still use existing old services and utilities
- During the migration, you don’t want to maintain both AngularJS and Angular code
What other migration strategies are out there?
These are the most commonly used strategies, and their disadvantages comparing to the strategy discussed later
- NgUpgrade – I personally experienced numerous performance issues as both Angular and AngularJS framework run Change Detection mechanism, and rewriting existing code might lead to duplicate services or components at some period of time, one in Angular and one in AngularJS
- Iframe – have duplicate services and components (old and new), need to bootstrap both frameworks which can cause performance issues in older browser
The common pitfalls for current migration strategies
As you understand from above, in all existing strategies you always need to run both frameworks (old and new) in order to perform the migration process.
Running both frameworks, in a hybrid mode, reduces application performance and eventually leaves you in this mode forever as the migration might never end.
Introducing ng-metadata
Imagine if you could write Angular (2+) code today and rewrite your JS code to Angular (2+) syntax, but still keep a single framework running — no performance degradation!
With this library, you could use the syntax and power of Angular (2+), as if you have the Angular framework running, including the @Component, @NgModule, @Injectable
decorators, change detection events (ngOnChanges(changes: SimpleChanges
), html binding decorators ([data]
, (events)
), etc…
Visit this great page below for further information
A high-level overview of the ng-metadata migration strategy (aka TL’DR)
- Start writing your new features in the ‘Angular’ (2+) way (using ng-metadata), make sure not to be coupled to any $scope or AngularJS dependencies
- On going, rewrite your existing code to ng-metadata (notice that this step will take the longest time in the migration process)
- Once done with steps 1 and 2, you should have all your code the Angular (2+) way
- Have the third party libraries API agnostic to your code, so when it’s time to replace them, your code won’t get broken
- Create an Angular (2+) router file, based on your current ui-router
- Install the Angular (2+) supported third party libraries
- Remove ng-metadata from your dependencies and replace them with the latest @angular dependencies
- You’ll notice that in my github repository, and my examples here, I don’t use ng-metadata directly. This is a good practice where you’re planning to refactor or use a third-party library, having a “buffer-zone” class that exports the necessary code and can be replaced in a single place when needed.
- Replace the AngularJS bootstrap to Angular
- Welcome to Angular!
Start migrating!
Let’s now begin our migration process.
Visit my github page and check-out the branches for each step.
Step 1 – Install ng-metadata
Install the following npm packages
npm install ng-metadata
npm install reflect-metadata
Step 2 – Start writing Components, Modules and Services — the Angular (2+) way!
A new service
- Notice
@Injectable('newService')
where we definenewService
as a string token, which is optional, but this actually gives us the ability to inject this service into ‘older’ services. (AngularJS idenitifes the injectable services by string token, whereas Angular does it by a class name as it uses Typescript) - I don’t import anything from ng metadata but from
my-decorators
as I mentioned in the high level steps above, as a single source where ng-metadata dependencies are imported, so later on I’ll be able to replace the ng-metadata into angular libs, in just one place
A new component
The $ctrl
would be removed later on when finally replace the framework to Angular.
A new module
Step 3 – bundle the AppModule into our JS application
Notice the ng-metadata’s bundle
method that ‘glues’ the new AppModule to our existing AngularJS main module
Step 4 – Ongoing changes, New and Old services
Because we declared a string token in Step 1 @Injectable('newService)
we can use our service in our existing components and services as injectable.
What’s next?
Now, go ahead and rewrite your components into the Angular syntax, and make sure you keep some development time for replacing the ui-router, third-party libraries, and existing AngularJS directives (ng-if to be ngIf, ng-repeat to be ngFor, etc…)
Last thing…
I’d like to thank Dima Abramovich (LinkedIn profile below) which helped a lot with this great and out-of-the-box migration process
Questions?
Feel free to contact me in any social media.