According to builtwith.com over 400,000 Angular 1 apps have been created and released into the wild. Moving to Angular 4 is a daunting prospect.
Most content online talks about how to migrate from 1 to 2 or 4 in a “big bang” approach. When your product processes millions every day, using the word “big bang” doesn’t engender a lot of support from senior managers or stakeholders.
In this talk, I’ll go through a real Angular 1 application and upgrade it “iteratively” to Angular 4. By the end, the Audience will have a step by step roadmap for how to upgrade.
Welcome to this workshop on how to migrate from Angular 1
As anyone who's done a large upgrade before knows.
- SHOW GIF -
It’s always a lot more complex
and risky than you thought at first.
But don’t worry.
What i’m going to be teaching you here is a technique that I used with my larger clients.
Those who really can’t use the word “big bang”.
Production app, lots of traffic.
Regulatory issues.
Can’t afford a down tools, upgrade and re-write whats broken approach.
Where nothing is released until the entire upgrade is complete.
I’m going to cover a technique thats
iterative
step by step approach
- at each stage you have a releasable product.
Can’t afford for developers to stop, tools down and develop.
[Q] Who here are in the process of migrating an AngularJS app or plan to do so in the next 3 months?
[Q] Of those how many of you have an SPA?
[Q] Of those how many of you are using UI-Router?
BIG BIG BIG CAVEAT SPA
More focussed on happy path than Joes workshop.
You are actively looking to migrate.
How is this structured?
First the theory behind what we are doing, the mental model.
This is going to be messy work.
But underlying it all is a simple structure and a clear set of rules.
If you’ve got a good grasp of those you can see through the mess to the other side.
Then i’ll describe the plan, something pretty generic that you can apply to your projects.
Then we’ll dive in with a real case study.
Now this is a workshop that I do that takes a whole day, so we can’t cover all it in the hour.
- I am going to cover the highlights.
I am going to show you snippets of code but i’m not going to write any, there just isn’t time and too much to get through.
Can find all the source code here.
PAUSE FOR 10 SECONDS
I’m not going to cover everything and I don’t expect you to remember everything.
But if you want to really understand what i’m doing then after this workshop you need to take a deep look at this project on github, everything is explained in much more depth in there.
[GOTO PAGE]
Show branches and pull request and instructions for installing.
My name is Asim, I run codecraft.tv where I do consulting and training on Angular and JS.
Recently consulting has been with enterprise customers or those dealing with complex legacy projects that they need to drag into the new age.
My name is Asim, I run codecraft.tv where I do consulting and training on Angular and JS.
Recently consulting has been with enterprise customers or those dealing with complex legacy projects that they need to drag into the new age.
I recently released a book on Angular 2 called Angular 2: From Theory to Practice
It was funded through some very generous backers on Kickstarter so it’s actually been released for free :)
You can find it on Amazon, iBooks, all the major online ebook stores.
Still for FREE
You can also get it from my site at angular.codecraft.tv which gets updated first and also has a bunch of videos that you can watch.
First a word mapping!
Demo the contacts application
Demo the contacts application
Demo the contacts application
Demo the contacts application
Demo the contacts application
Demo the contacts application
Demo the contacts application
When i mention an entity, i mean a component, service, filter, pipe, controller… a single thing in the app.
I’m going to show lots of slides with entities that are AngularJS and others that are Angular
Both are kinda red coloures.
To help people with color blindness i’ve changed
STEP DEMO
Demo Contacts App
Describe the different entities
We are gonna play a little quizz.
Can you guess the mental model from the picture?
Who can guess what this is?
[WALK AND TALK]
This is a simplified view of our app
Some top level directives/controllers which consume other directives/controllers and perhaps some services
While migrating we run both Angular 1 and Angular 4 in the same application!
We call this a Hybrid application.
So yeah, during the process of migration your users will have to download both but that’s the price you’ll have to pay.
Notice the EDIT and SERVICE (they have animations)
In a hybrid application some entities can be written in Angular 2 and some in Angular 1.
They work together and the application still runs.
[Q] Who is pretty comfortable with their knowledge of Zones?
The new application is running in Angular 2+ zone, and therefore it no longer needs calls to $apply().
The second mental model is that it’s chameleon.
We have a 1 entity and a 2 entity.
They don’t see each other.
So what we can do is we can upgrade 1
downgrade 2
Now an upgraded 1 can be used in an 2 entity or a 1 entity or even an upgraded 2 entity.
[WALK AND TALK]
Same goes for a downgraded Angular entity
[WALK AND TALK]
DI also still works.
We can have a downgraded Angular 2 service that’s injected into a 2 or 1 entity.
It’s also the same instance, so any data you set will be visible from the other entity
The final mental model
Each HTML node can only belong to either AngularJS or Angular 4
Example above the nodes are all controlled by AngularJS
Our goal therefore is to slowly transform all the entities to Angular 4.
You can go at this whichever direction you want.
An Angular 1 component is managed by Angular 1 and only knows Angular 1.
So if we tried to insert an Angular 2 entity into an Angular 1 entity
It wouldn’t blow up, the Angular 1 component just doesn’t know what card is so ignores it.
Downgrade it.
Wrapped in Angular 1 clothing
Still an Angular 2 component
Therefore it doesn’t see the Spinner control
Just like before that gets ignored!
So what we do is upgrade the spinner control
We wrap it in Angular 2 clothes so it can be recognised by Angular 2 components.
Angular 1 is always bootstrapped first and owns the bottom most view.
Think of the process of migration like a disease.
We infect an entity with Angular 4 .
I recommend you stat at the leaves.
Downgrade
Then we slowly spread up the app.
NOTICE we only need to downgrade the component that is being used by a 1 entity.
Then we spread up.
And up
And UP
Until eventually we’ve spread everywhere…
And then we get rid of 1
So everything is not all rosy
Not everything in Angular 1 can be migrated to Angular 2
Some things have to be re-written
Filters can’t be migrated.
Directives w/out templates and other features will need to be re-written.
What do I mean by a component?
Introduced in Angular 1.5
They are like a simplified and restricted version of a directive.
They are also a core part of Angular 4.
So moving to components now will make moving to Angular components in the future much easier.
Flip between step 1 and step 5
SHOW: ui-router config
SHOW: controller -> component config
SHOW: directives -> component
NOTE: Show $ctrl as syntax
Start with the router since those are typically the top level nodes in your application, you don’t have to but I find it’s a good place to start.
DEMO
Branch: Step 4
Show code for person list component: CONTROLLER -> COMPONENT
Show how you use these in the router config.
Converted all.
STILL RUNNING ANGULAR 1
Have some fun!
- Lets now start having some fun, es6’ify your app (or typescriptifying depending on how far you take it).
Use ES6 contstructs, classes, learn destructing, fat arrow syntax etc..
A great place to start is the services.
Angular 1 services written as ES6 classes are very easy to migrate to Angular 4.
There is no $resource in Angular 2
There is the Http module which looks very much like the Angular 1 $http module.
So spend this time to migrate away from $resource to $http.
Since ES6 classes are just constructor functions.
And services in Angular 1 are also just constructor functions and also map to Angular 2 services much better.
Spend this time to also move from using factory to service.
There is no $q in Angular 2
So maybe spend this time re-writing to use the new ES6 Promise syntax.
STEP 5
SHOW: Contact Resource - Use class and $http, constructor
SHOW: Contact Service - Use class, promises etc…
Now we’ve done all the prep work we are ready for the actual migrate.
We just include Angular 4
Create our main AppModule and then instead of bootstrapping that directly we duel boot with both Angular 1 and Angular 2.
All we are doing is adding Angular to our application.
We are now here.
A duel booted Angular 1 + 2 application, but all of the components/directives/services are all still Angular 1.
A great place to start is the services.
Angular 1 services written as ES6 classes are very easy to migrate to Angular 2.
STEP-6
Add packages to package.json
Add main.ts and bootstrap
It’s far easier in my opinion to just go bottom up.
Convert the leaves to Angular 2 and then move up the tree.
Services are going to be shared by lots of different things in our app so it makes sense to migrate those to Angular 2 first.
Thankfully due to our prep it’s going to be pretty easy.
Going back to our diagram we’ve got two services,
ContactService
ContactResource
Going to migrate ContactService to Angular 2 and then downgrade it so it can be used in Angular 1 and
since Resource is only going to be used by an Angular 2 service we migrate it to Angular 2 and don’t need to downgrade it.
When faced with a 3rd party Angular 1 service
You don’t control it.
You can’t migrate it.
So what do you do?
Re-write to Angular 2+ yourself
Find an Angular 2+ version
Upgrade to Angular 2+
STEP-7
ContactService
NOTICE:
@Injectable()
NgModule
downgradeInjectable
We still have our angular 1 module config at the bottom, but we add to our Angular 1 config a downgraded version of this service.
This is what makes our ContactService usable from both an Angular 1 and an Angular 2 entity.
Toaster
It’s not in the diagram to save space but the ContactService also relies on a 3rd party Angular 1 service called toaster?
We don’t control toaster, we can migrate it - so how do we make it injectable into an Angular 2 service?
We can try to write our own?
We can try to find if there is a 3rd party Angular 2 version?
We can upgrade an angular 1 service to use in an Angular 2 app.
Eventually we’ll have to figure out a solution, we can’t drop Angular 1 till we figure out a solution but for now we can use upgrade.
We can Upgrade an Angular 1 service to make it available in Angular 2 entity.
ajs-upgraded-providers.ts
Copy paste code.
We are getting close people!
Again start at the leaves.
In this case study i started at the card and spinner components.
Very similar to the services method we just migrate them to Angular 2 and then downgrade so they can be used in Angular 1.
Then it’s just the grind, slowly walking up the tree.
Migrating them to Angular 2 and the downgrading them to be used in Angular 1.
Most of the issues you’ll face are just about dependancies that you can’t control.
Re-write
Find
Upgrade
Most of the time you’ll want to opt for the second two, since the goal is to get rid of Angular 1.
STEP-8
person-list.component
@Component
Template, show how you now use Angular 2 syntax since it’s an Angular 2 component.
downguadecomponent
spinner
Same problem as the toaster.
Upgrade
Rewrite
Look for another 3rd party module.
card.component
Bindings -> Inputs
Need to use Ladda buttons - we’ve upgraded to an Angular 2 version.
Need to use ui-router links, hard code them.
No need to downgrade since we are only using this in Angular components now.
person-create.component
externalised the template code
UI Router Services, upgraded them.
search.component (can skip)
[Q] Who uses ng-model-options?
In Angular 2 the way to solve this problem is via model forms and Observables.
This time i went for a re-write, not the best but essentially using the same underlying library called spin.js to load the spinner.
Won’t go into depth you can look at the code and compare the branches yourself to see the changes.
Ok so we are there now
I can’t figure out how to easily break this up into small steps, so I call this the tiny pop.
NOT big bang.
Stop Hybrid mode.
Swap out ui-router <> Angular 2 Router
Find solutions to all the upgraded Angular 1 entities that you used.
For my demo app it’s actually the Toaster which we upgraded, in the end I found an Angular 2 one on the internet.
Basically remove all the old code.
Make sure you remove all the code referring to Angular 1 otherwise your build tools might pull that code it and bundle it with yours.
Now you are running a fun Angular 2 application!
Remove AngularJS which means Replacing remove final set of upgraded ng1 services/components (toaster)