A working Angular 1 & 2/4 app example with webpack.

I couldn’t find a working example of an hydrid angular 1 & 2 (or 4) using webpack.

Before any code or example how to to this configuration, you need to have your current angular 1 application working with webpack, that’s not going to be covered here, but if you need help on that ping me on twitter and I’ll create a post with all the information about.

As a personal choice I preffer Webpack over other tools like gulp, grunt or systemjs. This is a personal choice and the reasons are completly arbritary. So, don’t put time on arguments about that.

Note before start: It’s important to say that this article tries to put some light into one specific case, convert an angular1 in an hybrid angular 1 + 2/4 app. This means is not a perfect tutorial to follow, depends on what you have in your project, in your webpack config, in your current code, etc. So, is possible, or probably, will fail the first time, and you’ll need to work on specific errors to make it work. Don’t panic, and try to solve one by one any error you got. That’s whats a good programmer does, if any tutorial, article or post should be a perfect recipe, why use humans to do stuffs and not using machines directly?

Current configuration

In my case I have an Angular 1 app, version 1.6.5, with webpack using babel (es-2015). I didn’t have typescript before convert it to an Hybrid app, so I’ll explain how to add typescript support to your werbpack configuration.

It’s necessary to have Typescript on our stack becuase 99% of the angular2 example, codes, etc, use Typescript.

Adding Typescript to your stack

First step is to install some packages:

typings if for typescript types, we install it globally:

npm i -g typings

we install some dependencies:

typescript@latest --save
npm install angular2-polyfill --save
npm install zone.js@latest --save
npm install rxjs@latest --save

some dev-dependencies:

typings install dt~node --save-dev --global
npm install @types/core-js --save-dev
npm install typescript ts-loader --save-dev

finally, we install what we need to convert our app to an hybrid app (we need the package to upgrade and the lates angualr packages too):

npm install @angular/{upgrade,common,compiler,compiler-cli,core,forms,http,platform-browser,platform-browser-dynamic,platform-server,router,animations}@latest --save
npm install angular2-template-loader --save-dev

Setup webpack to handle TS (Typescript)

A few files needs to be updated/added:

webpack.config.js (or any file where you put your webpack config)

we need to add to process any .ts file, we’ll add to handle templates too.

{
  test: /\.ts$/,
  exclude: /node_modules/,
  loaders: ['ts-loader', 'angular2-template-loader']
}

we don’t need anything else on webpack to handle .ts files.

We need to create a tsconfig.json file:

{
  "compilerOptions": {
    "outDir": "./dist/",
    "target": "es5",
    "module": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "typeRoots": [
      "../node_modules/@types"
    ],
    "types": [
      "core-js"
    ],
    "lib": [
      "es2016",
      "dom"
    ]
  },
  "exclude": [
    "node_modules",
    "dist",
    "build"
  ]
}

Starting to plug the support for a Hybrid application

If you’ve read about, you know how this UpgradeAdapter works. The main concept is using UpgradeAdapter as a bridge between your angular2 and your angular1 application.

Our first step is to create our angular2 module, the module that defines the angular2 application. It’s important to understand this is a new and an independent application.

import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';

@NgModule({
  declarations: [],
  imports: [
    BrowserModule
  ],
  bootstrap: [],
  providers: []
})
export class AppModule { }

This is the minimal definition for an Angular2 application.

Connect our angular2 and angular1 application.

Now we need to connect both applications:

import "zone.js";
import { UpgradeAdapter } from '@angular/upgrade';
import { AppModule } from './app.module';

let upgradeAdapter = new UpgradeAdapter(AppModule);

upgradeAdapter.bootstrap(document.body, ['myApplicationModule']);

Some notes about this lines, the import "zone.js"; was to fix some problems after connect both applications, it may be possible you wont need it.

With the line upgradeAdapter.bootstrap(document.body, ['myApplicationModule']); we replace any code to initialize our application, before this I was using:

angular.element(document).ready(() => {
  angular.bootstrap(document, [moduleName], {
    strictDi: true
  });
});

Now we have both applications running and we can start to migrate from angular1 to angular2 or we can create new things in angular2 and use it on our angular1 application.

Use an angular2 service in our angular1 application

It’s important to understand what we need to do to allow our angular1 application access stuffs from angular2 application.

For example if you create a service in your angular2 applications, this is the code to make it visible in angular1:

import { MyServiceFromNG12 } from './myservice.from.ng2';
app.service('MyServiceFromNG12', upgradeAdapter.downgradeNg2Provider(MyServiceFromNG12));

note: ‘app’ is the variable I’m using to handle my angular1 application module. I defined that variable using:

let app = angular.module('myApplicationModule');

and now I can add things to my app after that definition.

Continue coding as normal

Now we have our Hybrid application, for example if we want to access our MyServiceFromNG12 on any part of our NG1 app we only put the MyServiceFromNG12 in the list of the injections and we can access as any other service.

class MyController {
  constructor(MyServiceFromNG12){
    this.list = MyServiceFromNG12.list();
  }
}