Upgrading AngularJS Applications
There are two main ways to incrementally upgrade your AngularJS application: using UpgradeModule and using downgradeModule. Nx helps you use both.
Using UpgradeModule
NgUpgrade is a library put together by the Angular team, which we can use in our application to mix and match AngularJS and Angular components and bridge the AngularJS and Angular dependency injection systems. We can call such an application a “hybrid application”, and the code required to bootstrap it an "upgrade module".
Setting up an Upgrade Module manually involves several steps and is easy to misconfigure. Nx provides a command that does it for you.
1ng g @nrwl/angular:upgrade-module legacyApp --project=myapp
This will add and set up UpgradeModule
, configure legacyApp
, and will add all the needed dependencies to package.json
.
Open the generated legacy-app-setup.ts
and you will find all the code needed to bridge the AngularJS and Angular applications.
Testing Hybrid Applications
For a lot of applications, just running one command is sufficient to convert your application into a hybrid application. That's not always the case--sometimes changes are required. To make this iterative process easier, Nx creates hybrid.spec.ts
, which you can use to make sure the upgrade module works.
After Upgrade Module
Nx sets up the upgrade module for you to help you get started with your upgrade process. To learn more on how to upgrade your application, once an upgrade module is set up, check out the following resources:
Talk: Upgrading Enterprise Angular Applications
In this talk at NgConf, Victor Savkin shows how to upgrade your application gradually, component by component, module by module using NgUpgrade and the Angular Router. He discusses the common problems developers face during such migrations and the patterns that can be used to remedy them.
<a href="https://www.youtube.com/embed/izpqQpD8RQ0" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://www.youtube.com/embed/izpqQpD8RQ0</a>
Blog: Upgrading Angular Applications
In this blog post series Victor Savkin covers similar topics but more in depth. He dives deep into NgUpgrade, including the mental model, implementation, subtleties of the API. Then he talks about different strategies for upgrading large AngularJS applications.
- NgUpgrade in Depth
- Upgrade Shell
- Two Approaches to Upgrading Angular Applications
- Managing Routers and URL
- Using NgUpgrade like a Pro: Lazy Loading AngularJS Applications
Using downgradeModule
While NgUpgrade provides a way to run Angular and AngularJS code side by side and bridge the dependency injection systems, it does take a bit of a performance hit. Reason being, you end up having both change detection systems running at the same time regardless of if you are hitting Angular or AngularJS code.
The Angular upgrade package provides a way to do "NgUpgrade Lite", which is the concept of running AngularJS and downgrading Angular to run when needed, as well as keeping the change detection systems separate. Angular change detection will only run on Angular code and AngularJS scope digest will only run on AngularJS code.
For finer grain control over application performance during conversion to Angular, the downgrade module approach is a good choice.
Setting up a Downgrade Module manually involves several steps and is easy to misconfigure. Nx provides a command that does it for you.
1ng @nrwl/angular:downgrade-module legacyApp --project=myapp
This will configure the AppModule
to not bootstrap the AppComponent
and instead set it up as an entry component. It will also configure main.ts
to bootstrap AngularJS and use the downgradeModule
to downgrade the Angular AppModule
to run in AngularJS.
Open main.ts
and you will find all the code needed to run AngularJS and include Angular code.
After Downgrade Module
Nx sets up the downgrade module for you to help you get started with your conversion process to Angular. Check out the blog post on Using Nrwl/Nx to Upgrade You AngularJS Applications to Angular to learn more about the differences between Upgrade and Downgrade Module.
From there, a good next step is to pick a slicing strategy for taking on incremental upgrades. To learn about the vertical and horizontal slicing strategies check out Two Approaches to Upgrading Angular Applications.
Upgrading/Downgrading Injectables and Components
Once you have decided on a slicing strategy you will move forward with converting AngularJS components (directives) and injectables to Angular and downgrading them to use them in the AngularJS bits as well as upgrading some of the AngularJS bits to be able to run in the Angular ones. The blog post NgUpgrade in Depth includes information on handling injectable and component conversions to Angular, which are the same way to do it for the Downgrade Module approach. Take a look at the sections on Dependency Injection and Component Integration to learn how to upgrade/downgrade injectables and components for use in AngularJS and Angular.
Controlling Change Detection
The other piece of the puzzle that you will need to handle is manually triggering change detection if your component tree consists of a combination of AngularJS and Angular components.
If you have an Angular component that has an AngularJS child component you may need to inject in $rootScope
and call $digest
after your Angular component does something to get the child AngularJS component to update:
1@Component({
2 selector: 'app-ticket-list',
3 templateUrl: './ticket-list.component.html',
4 styleUrls: ['./ticket-list.component.css'],
5})
6export class TicketListComponent implements OnInit {
7 @Input() tuskTickets;
8 notifyList = [];
9
10 constructor(@Inject('$rootScope') private rootScope: any) {}
11
12 onNotifyAll() {
13 this.notifyList = this.tuskTickets.map(function (t) {
14 return t.id;
15 });
16 // we need to force digest to trigger angularjs change detection
17 this.rootScope.$digest();
18 }
19}
Since the two change detection systems are kept separate in the Downgrade Module approach, you have to handle telling the other to run if the one you are in needs to affect the other.