AngularJS to Angular Upgrade Process (Part 1)
I believe we can all agree that web development is evolving at a rapid pace. Frameworks, libraries, tools, guidelines, best practices and new APIs appear out of nowhere every day. I bet there are many of us with ever-growing todo lists or to be more accurate, to-read lists and opened browser tabs with new technologies. AngularJS is around since 2009. 2009! That’s like forever in terms of the pace I previously spoke about. This is definitely one of the reasons why me, you or anyone else should be interested in upgrading from AngularJS to Angular. AngularJS won’t be supported forever and sooner or later will be deprecated. I think that every AngularJS line you write today, is already a technical debt. Angular was built with best practices and community feedback in mind. Angular codebase is definitely more cohesive, so not only is onboarding new programmers easier, but new programmers can be productive almost immediately as well.
Note: Angular 1.X was officialy renamed to AngularJS and Angular 2+ is just Angular.
Angular is a modern web framework. It relies on best practices and guidelines which have emerged over the past few years. In my opinion, the main reason to rewrite the framework from scratch was to implement and make use of all the feedback provided by the AngularJS community. Angular uses a so called uni-directional data binding from parent to child, which greatly improves the performance of the application and drops the need of a so called digest cycle. Another reason for me was the environment-agnostic way of Angular framework, i.e., Angular can be now rather easily used not only in a browser, but also in other environments, like native mobile or server.
Learning Angular is much more easier than AngularJS. There is no notion of scope, digest cycle, and $watch(). The change detection process is more straightforward and tweakable. While developing AngularJS applications I wasn’t really a fan of TypeScript or static typing. Now I have to admit, that I love TypeScript. I use Visual Studio Code as my default IDE and the integration is awesome. Last but not least, there is a great scaffolding support from Angular-CLI project, which will help you get up and running incredibly fast. Not only provides it great scaffolding support, but you’ll also benefit from the default devstack which makes it much easier to run tests, create production builds and see the changes you’ve made to the code insanely fast (this feature is also known as LiveReload).
Overview of the upgrade process
To upgrade, or not to upgrade?
In order to upgrade your AngularJS application to Angular, you have at least two choices. One of them is a complete rewrite from scratch. It obviously could be a lengthy process. Other than that, it is the one that is definitely almost impossible, or at least really tricky in terms of convincing your boss or technical manager. The other one is the iterative upgrade process, which I would like to describe in these series of articles.
I will follow the official recommendations to the upgrade process provided by the Angular team and add some of my personal ideas and recommendations to them. I will refer to this upgrade process as just the process.
The official guide is separated into 3 chapters. The first two are the actual consecutive parts of the process itself. The last chapter is a proof-of-concept example, where the sample PhoneCat application is upgraded to Angular. The first chapter is called Preparation. This chapter looks really straightforward when you glance over the sections. There are sections like Follow the Angular Style Guide or Use a Module Loader. Preparation chapter describes guidelines you should follow in your AngularJS application, introduces TypeScript and component directives from Angular 1.5. The second chapter looks more challenging. There are a lot of special cases which you could and probably will have in your application.
In the first part of these series, I will take just the Preparation chapter into consideration. In my opinion, this is the deal-breaker between a complete rewrite and the upgrade process. I believe that if the codebase is, let’s say out-of-shape, does not follow the style guide, uses a lot of pre-Angular 1.5 directives and almost no components, controllerAs and a lot of custom watches, the preparation step could be definitely more daunting and error-prone than the rest of the process.
Follow the Angular Style Guide
The first section in Preparation is called Follow the Angular Style Guide. This looks harmless, right? At the time of this writing, there are 30 sections, each with a bunch of rules you should follow in your AngularJS application. Some of them are rather simple and easy to follow, e.g., a module should be set only once or naming of the files.
However, there are some, which require great amount of discipline to follow or substantial amount of time to refactor later. One of them is Rule of 1, which states that there should be only 1 component defined in each file, e.g., you should have a separate file for every module, factory, filter and controller. Not only promotes it easier unit testing, mocking, maintanability, avoids source control and namespacing collisions, but also makes it easier to upgrade AngularJS application one component at a time.
Another one is Folders-by-Feature Structure, which promotes grouping of AngularJS components based on their feature, rather than type. There are a lot of AngularJS applications with folders like directives, controllers, filters, etc. This rule says, that in order to align your application with Angular structure, you should group your directives, controllers and filters into directories like order, session, people, flights, etc. according to the specific needs of your application. This rule is coupled with Modularity, which encourages splitting your application into one root App Module and a few Feature Modules.
Using a Module Loader
Considering you did follow the Angular Style Guide, especially the Rule of 1, you now have a considerable amount of rather small files. It could be concatenated or loaded using HTTP2, but nowadays is more convenient to use Module Loader, it can simplify the loading process and help us to provide correct order of dependencies.
In order to solve these issues we can introduce a Module Loader into our application. The current state-of-the-art is Webpack. It is easy to use and very powerful at the same time. Other than that, Angular uses Webpack by default (if you want to use Angular-CLI), so in my opinion, it is the safest bet. However, you still could use other solutions, such as Browserify, or SystemJS. Using Webpack, we can very easily integrate the TypeScript, use linters, optimize initial load times and much more.
TypeScript is a superset of ECMAScript 2015 with additional neat features like Interfaces and static typing. There are a lot of great articles and case studies about the benefits of static typing. From my personal experience, I can tell the main benefit is noticing typos and errors specific to types even before you run the code in a browser, there is also a significant improvement of IDE auto-completion features.
Not only uses Angular TypeScript by default, but it has also been written in TypeScript. TypeScript gets us another step closer to the Angular application. Services and controllers can be turned into classes and we can also benefit from features like arrow functions, default function parameters and destructuring. You can use Angular without TypeScript, but I highly recommend using TypeScript. TypeScript will definitely make your life easier and your programmers productive. On top of that, the language is more convenient to pick up for someone with Java, C# or other statically typed language background.
Using Component Directives
Angular does not use the notion of a directive as we know it from AngularJS. Angular applications are made of components. Component is a group of HTML elements and other components, with specific inputs, outputs and logic tied to it. These components should be easily reusable and testable. If your project uses AngularJS <1.5, I suggest you rewrite all your directives to AngularJS 1.5 components, which are basically just a syntactic sugar over directives with some neat default attributes. Using components will definitely make your upgrade seamless. However, there are a few changes to the way you should write your components. You can’t use the watch function in Angular, but there is an onChanges component lifecycle hook or doCheck. The ngOnChanges hook is called every time some input value changes.
Let’s get to work!
I think, that these preparation steps could take a considerable amount of time, however it really depends on the current state of the codebase and its alignment with these steps. There could certainly be some applications, where the amount of work would be much greater than a complete rewrite. In the next part we will take a look at the Upgrade Module and we try to bootstrap a hybrid AngularJS/Angular application.
I would like to thank Víťa Plšek from Angular.cz for reviewing this article and for his valuable suggestions.
Matej Minárik, Front-end expert at PrimeHammer