2/2/17

Using Angular2 Components Inside Angular1 Project

Dreaming About Upgrade

If you working on project that built with angular1 for historical reasons and dreaming about move to angular2 - this article is for you.
Yes, it is possible to move to angular2 make little changes step by step, without breaking the running code of your application. In this article i will take this angular-seed repo and try to make it run with some angular2 component included.

Step 1 - Bootstrap Angular Different Way

Usually the angular is attached to HTML using ng-app directive but there is another way to bootstrap angular to your application - using angular.bootstrap utility:


angular.bootstrap(document.body, ['myApp'], {strictDi: true});

You can view source at this branch

Step 2 - Migrating to Typescript

To move project to typescript you need :
1. rename all the files to end with ts instead of js (meanwhile leave files finishing with 'test' and not rename them to ts)
2. install typescript compiler:

npm i typescript -D
3.create tsconfig.json file at root directory

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "suppressImplicitAnyIndexErrors": true
  }
}

4. install type definitions for angular and other dependencies
npm install @types/angular -D
If all the installations succeed - after running
tsc -p .
command all ts files should have their ".js" and "map.js" copies - appear near them.


You can view source at this branch

Step 3 - Move application to load dependencies from node modules

Why? Mostly from reason that angular2 recommend to load dependencies this way instead of using bower. So, since node_modules directory located at project root we need to modify index.html so all the urls will stay correct:
Insert base tag inside head tag of your index.html


<base href="/app/">

Also you will need to change "start" script inside package.json:

"start": "http-server -a localhost -p 8000 -c-1 ./",

Now you can install all the dependencies like angular through NPM:

    "angular": "^1.6.1",
    "angular-route":"^1.6.1",

Don't forget to change the paths inside the index.html:

  <script src="/node_modules/angular/angular.js"></script>
  <script src="/node_modules/angular-route/angular-route.js"></script>

Now make sure that after you run
tsc -p ./
and then:
npm start
command you can see the project running:

You can view the full code on this branch

Step 4 - Install Systemjs Module Loader

Module Loader - a way to make javascript to import or export different javascript types (like classes) from one file to other. There are several javascript module loaders such as Webpack, Browserify, Systemjs - for our tutorial we will use systemjs.

npm install systemjs -D
After installation lets try to include the systems script to "index" page:

  <script src="/node_modules/systemjs/dist/system.src.js"></script>

Important: systemsjs uses its own configuration file - systems.config You may place it in the "app" directory:


/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': '/node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: '/app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',      
      '@angular/upgrade/static':'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });
})(this);

This files points to system module loader where the scripts located. Lets see if it loaded now in the chrome developer tools:
After we can see everything is still working lets add angular2 dependencies to package.json:

    "@angular/common": "~2.4.0",
    "@angular/compiler": "~2.4.0",
    "@angular/core": "~2.4.0",
    "@angular/forms": "~2.4.0",
    "@angular/http": "~2.4.0",
    "@angular/platform-browser": "~2.4.0",
    "@angular/platform-browser-dynamic": "~2.4.0",
    "@angular/router": "~3.4.0",

    "angular-in-memory-web-api": "~0.2.4",
    "systemjs": "^0.20.4",
    "core-js": "^2.4.1",
    "rxjs": "5.0.1",
    "zone.js": "^0.7.4"
You also must point to systems that you main module is inside "app" directory:
index.html

    <script src="systemjs.config.js"></script>
    <script>
      System.import('/app').catch(function(err){ console.error(err); });
    </script>

Important: you must remove main.js reference from index.html
And run again:npm install and after :tsc -p .

If everything is OK you should refresh and see the app running as usual.

Little Experiment

Now lets try to import some file into main.ts file using import command:
main.ts


import './app'
declare var angular: ng.IAngularStatic;//must not override global angular
angular.bootstrap(document.body, ['myApp'], { strictDi: true });

Now you can remove app.js reference from index.html and see that app still running (since the code imported by systemjs!)

You can view full code on this branch

Step 05 - Install Angular Upgrade

Now we about to enter cherry-in-the-cake zone of this article - start using angular2 and angular1 in the same project

 npm i @angular/upgrade -D
This angular2 module makes you to be able to include angular2 modules into your angular1 project.
Lets add angular2 module named AppModule
app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static'
@NgModule({
  imports: [
    BrowserModule,
    UpgradeModule,
  ],
})
export class AppModule {
  ngDoBootstrap() {}
}

Now the only thing left is to inject your old myApp module angular2 way:
main.ts

/*angular.bootstrap(document.body, ['myApp'], {strictDi: true});*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  upgrade.bootstrap(document.body, ['myApp']);
});

Voula! you running angular2 and angular1 together now!
You can view source code on this branch

Thanks for reading

No comments:

Post a Comment

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...