Running AngularJS 1.6 in Angular 5 (side by side)

Hiroki Gota
Code道
Published in
8 min readMar 28, 2018
Side by side

We’d like to share one of the migration strategies from AngularJS to Angular. This blog is part 1 of 3, please also read part 2: Building new features in Angular 5 and part 3: Build, deploy and beyond.

At Lapis, We run a number of AngularJS (1.2.x ~ 1.6.x) apps in production which were built around 2012 ~ 2015. Their main tech stack components are:

  1. Angular 1.x
  2. Bootstrap 3.x
  3. Leaflet
  4. OpenLayer
  5. LocalStorage (ngstorage)
  6. Font Awesome
  7. Moment JS (Date/time)
  8. Grunt for build
  9. Docker for the build process

Many of the apps are stable and there is no reason to migrate/upgrade (commercially) to Angular 5 (6 is coming soon). However, some of the apps have on-going enhancement work and require new libraries for new features.

Problem

When you need a new library or external capabilities, most libraries (Angular wrapper etc.) are now only targeting Angular 2+.

Data Farming Mapping Website is a good example. The client wanted to add a shopping cart capability including eWay integration. While it is entirely possible to stay in 1.6, there was a risk of adopting external capabilities that are no longer maintained.

ngUpgrade: Run AngularJS and Angular side by side

This topic is not new and a lot of materials have been published over the last couple of years (Since Angular 2). We learned a lot through a number of blogs and official documentation, which were kind of outdated as Angular was evolving so quickly especially since early 2017 and after March 2018.

Must read

It is still a good idea to go through the history of the migration process as well as reading the official documentation:

  1. One of the recent blogs is about this topic: https://medium.com/code-divoire/a-story-of-ngupgrade-bringing-an-angularjs-application-from-1-6-to-angular-4-84eae4434010
  2. Insight of ngUpgrade, very helpful to understand the architectural part of ngUpgrade: https://blog.nrwl.io/ngupgrade-in-depth-436a52298a00
  3. A bit outdated but it provides the mechanics in detail: https://angular.io/guide/upgrade
  4. The only working implementation found (via the 1st blog): https://github.com/manfredsteyer/ngUpgrade-without-preparation

Case Study: Data Farming Mapping Website

https://maps.datafarming.com.au/#

AngularJS app overview

We selected the Data Farming app as a migration candidate as we were about to implement some new features including an e-commerce capability using eWay and a custom shopping cart for downloadable shapefiles.

The app was originally created in order to demonstrate an API capability, however, it quickly evolved to an app directly used by farmers and consultants. Technically speaking, it has the following characteristics:

  1. AngularJS 1.6 + Angular Material, Grunt base and a few libraries including Auth0, OpenLayer 3, jsPDF and introJS
  2. The app is relatively small (Login; List Farms; Draw paddocks in the map; Upload KML/Shapefiles; View NDVI images for paddock and print PDF)
  3. Building a new feature which requires a new library (eWay) and new UX (shopping cart, purchase history etc.)
  4. The existing code base needs to be reviewed prior to extending as it was built for a simple prototype

Migration step summary

The following are the steps we took after a lot of reading. There are different migration strategies available in the official documentation, however, our preference is running side by side with Angular 5 being the main application.

  1. Create Angular 5 application using Angular CLI (1.7.3)
  2. Copy an existing Angular JS app (should be 1.6.x and refactored so the structure of the code is feature-based and each file has a single impl)
  3. Migrate JS dependencies (Switch npm or copy bower_components)
  4. Fix template paths in both JS and HTML
  5. Migrate scss files and fix import paths
  6. Fix API proxy path from Grunt to Angular CLI
  7. Fix minor CSS issues caused by an introduction of view-container and view-frame
  8. Regression test (It seems all working at this stage, have a good test by QA)
  9. Add Angular Routing and introduce a new page
  10. Switch between AngularJS page and Angular page

Migration steps

Create Angular 5 application using Angular CLI (1.7.3)

Firstly, create an Angular 5 app using Angular CLI. (Used Node 8.10.0 LTS)

npm install -g @angular/cling new ng52 --style=scss
cd ng52
ng serve

Copy an existing Angular JS app into src/ng1

The app is s Grunt based Angular JS 1.6 app using Bower for web dependencies, NodeJS for the build process and SCSS for css processing.

We firstly copied the app directory into src of Angular 5 app:

Migrate JS dependencies (copy bower_components)

Most of our JS dependencies are from bower, which essentially copies GitHub repositories into bower_components. We also have some dependencies fetched via CDN as well as embedded JS library.

Whilst it is possible to switch all dependencies into npm, our approach is to simply copy the required dependencies as a part of embedded scripts in Angular 5.

This decision is based on the time we want to spend as well as these dependencies will not be updated during the migration. (Of course, all of these can be migrated over a period of time when needed).

Bower components copied into src/ng1
Some libs are still using CDNs

When all dependencies are copied, simply list them in scripts of .angular.cli.json, in the same order as the original index.html. (followed by the application code)

.angular.cli.json

Bootstrap AngularJS in Angular

At this point, Angular JS can be bootstrapped and show a page as all JS runtime is available. First, install the upgrade module and imports the module:

npm install @angular/upgrade --save
app.module.ts

Then bootstrap AngularJS app in app.component.ts

app.component.ts

Lastly, create a template for AngularJS app in app.component.html

app.component.html

Run the application by ng serve and we see AngularJS app running with a few errors including no style and 404 errors for HTML templates.

Fix template paths in both JS and HTML

At this point, AngularJS app is served in src/ng1/app directory and breaks the paths for partial htmls:

404 error for partial html templates

To fix 404 errors, add ng1 in .angular-cli.json

.angular-cli.json

Paths in HTML (ng-include) and js (routing, directives etc.)

before
after
before
after

After fixing the templates, we now see the page without style

Home page without styles

Migrate scss files and fix import paths

AngularJS app uses scss, which is supported by Angular CLI. You can specify it when you create an app (or update in .angular-cli.json):

"defaults": {
"styleExt": "scss",
"component": {}
}

Once scss is setup, then specify all scss files in styles of .angular-cli.json. We took this approach instead of fixing @import of scss so these dependencies are visible in .angular-cli.json and we can reuse them in Angular 5 app.

Then fix variable references and path errors

Fix API proxy path from Grunt to Angular CLI

AngularJS app uses Grunt proxy, which we can simply replace with proxy.conf.json:

{
"/ndvi": {
"target": "http://localhost:3010",
"secure": false
}
}

Start app with

"start": "ng serve --proxy-config proxy.conf.json",

Fix minor CSS issues by view-container and view-frame

The example GitHub repo has the following app.component.html. AngularJS app is rendered in ng-view and Angular 5 app is rendered in router-outlet.

<div class="view-container">
<div ng-view class="view-frame"></div>
<!-- router-outlet></router-outlet -->
</div>

AngularJS app does not expect this extra divs and we have to fix css accordingly.

Regression test

AngularJS app seems all working at this stage, so we pass it to QA and make sure every part of the app is working.

Add Angular Routing and introduce a new page

AngularJS app is now successfully running in Angular 5 app, it is time to introduce a brand new page in Angular 5. We can just run a few Angular CLI command and create a component and a module.

ng g component home

Switch between AngularJS page and Angular 5 page

The last part is to switch the routing between AngularJS and Angular 5. We took the following implementation from the example GitHub repo:

app.module.ts

CustomHandlingStrategy checks the URL and decides whether the URL passed should be handled by Angular 5, otherwise, simply forward to the AngularJS app.

The result

We’ve successfully run 2 apps side by side!

AngularJS
Angular 5

Next step

We’re now ready to start a new feature in Angular 5 including how to share the common resources such as header/footer, Local storage etc.

We’ll share our findings in the next post.

Part 2 is now available:

Running AngularJS 1.6 in Angular 5 (side by side) Part 2: Build new features in Angular 5

--

--

Hiroki Gota
Code道
Editor for

I am a Software Architect at Lapis, Melbourne Australia. I enjoy building end to end custom solutions with a Kaizen spirit in a team environment.