angular 2 migration - jhipster meetup 6

51
JHipster 4.0 The Angular Migration by Flavien Cathala and William Marques

Upload: william-marques

Post on 16-Apr-2017

1.097 views

Category:

Internet


1 download

TRANSCRIPT

Page 1: Angular 2 Migration - JHipster Meetup 6

JHipster 4.0The Angular Migration

by Flavien Cathala and William Marques

Page 2: Angular 2 Migration - JHipster Meetup 6

Who are we ?William Marques Flavien Cathala

@[email protected]

JHipster MemberIppon Consultant

@[email protected] MemberEpitech Student

Page 3: Angular 2 Migration - JHipster Meetup 6

Summary

1.Introduction

2.Prepare your migration

3.Angular 2 ecosystem

4.Step-by-step migration

5.After the migration

Page 4: Angular 2 Migration - JHipster Meetup 6

Migration on JHipsterJHipster Team

VictorJulien Deepu William

Flavien Sendil Kurma

n

Page 5: Angular 2 Migration - JHipster Meetup 6

Migration on JHipsterContributors

Chris Thielen

UI Router founder

Sean Larkin

Webpack member

Page 6: Angular 2 Migration - JHipster Meetup 6

Migration on JHipsterChronology

Start of migration

June

Migration to Webpack

November

Entities

Tests

December

End ?

JanuaryDependenci

es

September

Page 7: Angular 2 Migration - JHipster Meetup 6

Angular 2

- New syntax- New concepts

Officially released in September 2016 with:

Page 8: Angular 2 Migration - JHipster Meetup 6

AngularJS vs Angular 2

Javascript TypescriptMVC Component

OrientedPromise Observable

AngularJS Angular 2

Page 9: Angular 2 Migration - JHipster Meetup 6

Why migrating ?

- Better performances- More adapted to mobile terminals- Better productivity- AngularJS will be deprecated

Page 10: Angular 2 Migration - JHipster Meetup 6

PREPARE YOURSELF

Page 11: Angular 2 Migration - JHipster Meetup 6

Follow the John Papa styleMajor rules :

Folder-By-Feature

Scope Isolation (controllerAs “vm”)

IIFE (avoid minification conflicts)

https://github.com/johnpapa/angular-styleguide/tree/master/a1

(that’s him)

Page 12: Angular 2 Migration - JHipster Meetup 6

Be modular !Create module files and declare your controllers and factories there

Code is cleaner

Easy module loader setup

Source: https://github.com/tuchk4/requirejs-angular-loader

Page 13: Angular 2 Migration - JHipster Meetup 6

Do ComponentsOnly available in >= 1.5.x

Easy switch to Angular 2 Component

Promote best practices (scope isolation)

One-way binding possible

angular.module('heroApp').component('heroDetail'

, {

templateUrl: 'heroDetail.html',

controller: HeroDetailController,

bindings: {

hero: '='

}

});

Page 14: Angular 2 Migration - JHipster Meetup 6

BONUS 1 : Do TypeScriptSpoiler : You will write TypeScript with Angular 2 (widely recommended)

Add classes, types, imports in your code

Very easy migration to Angular 2

https://codepen.io/martinmcwhorter/post/angularjs-1-x-with-typescript-or-es6-best-practices

Page 15: Angular 2 Migration - JHipster Meetup 6

BONUS 2 : YarnNew package manager (another one)

Much faster

Easy to use (same command as NPM)

Avoid “works on my machine” issue

Offline Installation

Page 16: Angular 2 Migration - JHipster Meetup 6

Angular 2 ecosystem

Page 17: Angular 2 Migration - JHipster Meetup 6

Module loaderWhy ?

- Code complexity

- Performances- Avoid injection of huge number of files in index

Page 18: Angular 2 Migration - JHipster Meetup 6

Module loader

Complexity ** **Maintainabilit

y* ***

Performances * ***

SystemJS WebpackWhich one ?

Page 19: Angular 2 Migration - JHipster Meetup 6

Module loaderWhy Webpack ?

Page 20: Angular 2 Migration - JHipster Meetup 6

Migration to Webpack

+

Page 21: Angular 2 Migration - JHipster Meetup 6

Webpack

webpack.common

webpack.dev

webpack.prod

polyfills

vendor

Page 22: Angular 2 Migration - JHipster Meetup 6

webpack.dev.js const webpackMerge = require('webpack-merge');

const commonConfig = require('./webpack.common.js');const ENV = 'prod';

module.exports = webpackMerge(commonConfig({env: ENV}), { output: { filename: '[hash].[name].bundle.js', chunkFilename: '[hash].[id].chunk.js' }, plugins: [ new ExtractTextPlugin('[hash].styles.css') ]});

Webpackwebpack.prod.js

const webpackMerge = require('webpack-merge');const commonConfig = require('./webpack.common.js');const ENV = 'dev';

module.exports = webpackMerge(commonConfig({env: ENV}), { module: { rules: [{ test: /\.ts$/, loaders: [ 'tslint' ] }] }, plugins: [ new BrowserSyncPlugin({ host: 'localhost', port: 9000, proxy: 'http://localhost:8080' }), new ExtractTextPlugin('styles.css'), new webpack.NoErrorsPlugin() ]});

Page 23: Angular 2 Migration - JHipster Meetup 6

polyfills.ts

import 'bootstrap/dist/css/bootstrap.min.css';import 'font-awesome/css/font-awesome.min.css';

Webpack

vendor.ts

import 'reflect-metadata/Reflect';import 'zone.js/dist/zone';

module.exports = function (options) { const DATAS = { VERSION: JSON.stringify(require("../package.json").version), DEBUG_INFO_ENABLED: options.env === 'dev' }; return { entry: { 'polyfills': './src/main/webapp/app/polyfills', 'vendor': './src/main/webapp/app/vendor', 'main': './src/main/webapp/app/app.main' }, resolve: { extensions: ['.ts', '.js'], modules: ['node_modules'] }, output: { path: './target/www', filename: '[name].bundle.js', chunkFilename: '[id].chunk.js' },

webpack.common.js

Page 24: Angular 2 Migration - JHipster Meetup 6

WebpackHow to run Webpack ?webpack --watch --config

webpack/webpack.dev.js

webpack -p --config webpack/webpack.prod.js

Using NPM scriptspackage.json

"scripts": { "webpack:dev": "webpack --watch --config webpack/webpack.dev.js", "webpack:prod": "webpack -p --config webpack/webpack.prod.js" }

npm run webpack:dev

npm run webpack:prod

Command lines

Page 25: Angular 2 Migration - JHipster Meetup 6

Package managers

Page 26: Angular 2 Migration - JHipster Meetup 6

THE MIGRATION

Page 27: Angular 2 Migration - JHipster Meetup 6

Migration Plan : Bottom Up

1.Setup migration (install Angular 2 packages, the hybrid app)

2.Migrate small controllers, services, templates (leafs) and then their parents

3.Migrate routes

4.Check 3rd party dependencies (Angular UI, Angular Translate)

5.Remove AngularJS Code / Dependencies

6.Bootstrap your Angular 2 App !

Page 28: Angular 2 Migration - JHipster Meetup 6

upgradeAdapter

Incremental Update (hybrid app)Upgrade your Angular 1 Services, Controllers…Downgrade your Angular 2 Services, Components… Bad performance (temporary solution)

Why ?

Page 29: Angular 2 Migration - JHipster Meetup 6

SetupRemove ng-app and strict-di attribute in your template

Create an app.main.ts :upgradeAdapter.bootstrap(document.body, ['myApp.app'], {strictDi: true});

Page 30: Angular 2 Migration - JHipster Meetup 6

Setup

import * as angular from 'angular';

import { UpgradeAdapter } from '@angular/upgrade';

import { forwardRef } from '@angular/core';

import { Ng2BasicAppModule } from './app.ng2module';

export var upgradeAdapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() =>

Ng2BasicAppModule));

Create an upgrade_adapter.ts file

Page 31: Angular 2 Migration - JHipster Meetup 6

UsageDowngrade an Angular 2 Component to use it in your Angular 1 App, add in your module file :

For a service :.directive(‘home’, <angular.IDirectiveFactory> upgradeAdapter.downgradeNg2Component(HomeComponent))

.factory(‘example’, adapter.downgradeNg2Provider(Example));

Page 32: Angular 2 Migration - JHipster Meetup 6

Controller Migration

- Remove the IIFE

- Remove the $inject

- Use the @Component annotation

- Replace controller function by class

- Remove controller declaration (angular.module…)

Page 33: Angular 2 Migration - JHipster Meetup 6

Controller Migrationimport { Component, OnInit, Inject } from '@angular/core';import { StateService } from "ui-router-ng2";import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';import { Account, LoginModalService, Principal } from "../shared";

@Component({ selector: 'home', templateUrl: './home.html'})export class HomeComponent implements OnInit { account: Account; modalRef: NgbModalRef;

constructor( private principal: Principal, private $state: StateService, private loginModalService: LoginModalService ) {}

ngOnInit() { this.principal.identity().then((account) => { this.account = account; }); }

isAuthenticated() { return this.principal.isAuthenticated(); }

login() { this.modalRef = this.loginModalService.open(); }}

(function() { 'use strict';

angular .module('ng2FinalApp') .controller('HomeController', HomeController);

HomeController.$inject = ['$scope', 'Principal', 'LoginService', '$state'];

function HomeController ($scope, Principal, LoginService, $state) { var vm = this;

vm.account = null; vm.isAuthenticated = null; vm.login = LoginService.open; vm.register = register; $scope.$on('authenticationSuccess', function() { getAccount(); });

getAccount();

function getAccount() { Principal.identity().then(function(account) { vm.account = account; vm.isAuthenticated = Principal.isAuthenticated; }); } function register () { $state.go('register'); } }})();

Page 34: Angular 2 Migration - JHipster Meetup 6

Same refactoring as controllers

Add your service in the providers array of your Angular 2 Module in order to inject it in your Angular 2 Components

Downgrade it using the upgradeAdapter in your Angular 1 Module :

Service migration

.factory('example', adapter.downgradeNg2Provider(Example));

Page 35: Angular 2 Migration - JHipster Meetup 6

Service Migration

1 2

(function() {

'use strict';

angular

.module('ng2FinalApp')

.factory('LogsService', LogsService);

LogsService.$inject = ['$resource'];

function LogsService ($resource) {

var service = $resource('management/jhipster/logs', {}, {

'findAll': { method: 'GET', isArray: true},

'changeLevel': { method: 'PUT'}

});

return service;

}

})();

import { Injectable } from '@angular/core';

import { Http, Response } from '@angular/http';

import { Observable } from 'rxjs/Rx';

import { Log } from './log.model';

@Injectable()

export class LogsService {

constructor(private http: Http) { }

changeLevel(log: Log): Observable<Response> {

return this.http.put('management/jhipster/logs', log);

}

findAll(): Observable<Log[]> {

return this.http.get('management/jhipster/logs').map((res:

Response) => res.json());

}

}

Page 36: Angular 2 Migration - JHipster Meetup 6

Angular 1 Dependency in Angular 2 ?

Upgrade the Angular 1 provider in your module file, using the upgradeAdapter:

Use the @Inject annotation in your Angular 2 controller/service constructor :

Same for Angular 1 lib dependencies ($state, $rootScope… )

@Inject('heroes') heroes: HeroesService

adapter.upgradeNg1Provider('heroes');

Page 37: Angular 2 Migration - JHipster Meetup 6

Routes Migration

Angular 2 Router UI-Router NG2

Default solution for Angular TeamInspired by AngularJS UI RouterComponent Oriented

Easy migration from UI Router NG 1Visualizer feature

Breaking changes from UI Router NG1 Not the official Solution

Final Decision : UI-Router NG2, because of their contribution to JHipster

NG2 Router or UI-Router ?

Page 38: Angular 2 Migration - JHipster Meetup 6

Route Migration: SetupInstall ui-router-ng1-to-ng2 and ui-router-ng2 NPM packages

Add uirouter.upgrade module dependency in your Angular 1 Module

Add Ng1ToNg2Module in your Angular 2 Module

let ng1module = angular.module("myApp", [uiRouter, 'ui.router.upgrade']);

@NgModule({

imports: [ BrowserModule, Ng1ToNg2Module ]

}) class SampleAppModule {}

Page 39: Angular 2 Migration - JHipster Meetup 6

Route Migration : UpgradeAdapterIn your upgrade_adapter.ts file, add these lines :

import { uiRouterNgUpgrade } from "ui-router-ng1-to-

ng2";

uiRouterNgUpgrade.setUpgradeAdapter(upgradeAdapter);

Page 40: Angular 2 Migration - JHipster Meetup 6

Route migration : refactoringimport { RegisterComponent } from './register.component';import { JhiLanguageService } from '../../shared';

export const registerState = { name: 'register', parent: 'account', url: '/register', data: { authorities: [], pageTitle: 'register.title' }, views: { 'content@': { component: RegisterComponent } }, resolve: [{ token: 'translate', deps: [JhiLanguageService], resolveFn: (languageService) => languageService.setLocations(['register']) }]};

(function() { 'use strict';

angular .module('ng2FinalApp') .config(stateConfig);

stateConfig.$inject = ['$stateProvider'];

function stateConfig($stateProvider) { $stateProvider.state('register', { parent: 'account', url: '/register', data: { authorities: [], pageTitle: 'register.title' }, views: { 'content@': { templateUrl: 'app/account/register/register.html', controller: 'RegisterController', controllerAs: 'vm' } }, resolve: { translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) { $translatePartialLoader.addPart('register'); return $translate.refresh(); }] } }); }})();

Page 41: Angular 2 Migration - JHipster Meetup 6

Route migration : Route Declarationlet ACCOUNT_STATES = [ accountState, activateState, passwordState, finishResetState, requestResetState, registerState, sessionsState, settingsState];

@NgModule({ imports: [ Ng2BasicSharedModule, UIRouterModule.forChild({ states: ACCOUNT_STATES }) ], declarations: [ ActivateComponent, RegisterComponent, PasswordComponent, PasswordResetInitComponent, PasswordResetFinishComponent, SessionsComponent, SettingsComponent ], providers: [ SessionsService, Register, Activate, Password, PasswordResetInit, PasswordResetFinish ], schemas: [CUSTOM_ELEMENTS_SCHEMA]})export class Ng2BasicAccountModule {}

Add your routes in a variable and then import them using UIRouterModule.forChild :

Page 42: Angular 2 Migration - JHipster Meetup 6

Templates migration

ng-class [ngClass]ng-click (click)

ng-if *ngIfng-model [(ngModel)]ng-repeat *ngFor

AngularJS Angular 2

Page 43: Angular 2 Migration - JHipster Meetup 6

Templates migration<div class="modal-header"> <button class="close" type="button"

(click)="activeModal.dismiss('closed')">x </button> <h4 class="modal-title">Sign in</h4></div><div class="modal-body"> <div class="row"> <div class="col-md-4 col-md-offset-4"> <h1 jhi-translate="login.title">Sign in</h1> </div> <div class="col-md-8 col-md-offset-2"> <div class="alert-danger" *ngIf="authenticationError"> <strong>Failed to sign in!</strong> </div> </div> <div class="col-md-8 col-md-offset-2"> <form class="form" role="form" (ngSubmit)="login()"> <div class="form-group"> <label for="username">Login</label> <input type="text" class="form-control" name="username"

id="username" [(ngModel)]="username"> </div>

<div class="modal-header"> <button type="button" class="close"

ng-click="vm.cancel()">&times;</button> <h4 class="modal-title">Sign in</h4></div><div class="modal-body"> <div class="row"> <div class="col-md-4 col-md-offset-4"> <h1 data-translate="login.title">Sign in</h1> </div> <div class="col-md-8 col-md-offset-2"> <div class="alert-danger" ng-show="vm.authenticationError"> <strong>Failed to sign in!</strong> </div> </div> <div class="col-md-8 col-md-offset-2"> <form class="form" role="form" ng-submit="vm.login($event)"> <div class="form-group"> <label for="username">Login</label> <input type="text" class="form-control"

id="username" ng-model="vm.username"> </div>

Page 44: Angular 2 Migration - JHipster Meetup 6

Dependencies migration

- angular-ui ng-bootstrap- angular-translate ng2-translate

Some external dependencies needed to be replaced/updated:

- ...

Page 45: Angular 2 Migration - JHipster Meetup 6

Remove AngularJS

- Remove upgradeAdapter- Remove all AngularJS files

Once everything has been migrated:

Page 46: Angular 2 Migration - JHipster Meetup 6

CONCLUSION

Page 47: Angular 2 Migration - JHipster Meetup 6

Migration Feedback

A lot of new technologies and architecturesDifficult processSome libs are poorly documented and in alphaOnly a few projects already migratedMany different choices (Router, Module Loader)Don’t do it yourself : Use JHipster ;-)

Page 48: Angular 2 Migration - JHipster Meetup 6

About Angular 2...

Modern approach (Component oriented)

TypeScript Features (types, ES6)

Cleaner code

Less tools (only NPM)

Page 49: Angular 2 Migration - JHipster Meetup 6

What’s next ?

Router discussions

Hot Module Loader

Ahead Of Time compilation

Finish migration for all configurations

Page 50: Angular 2 Migration - JHipster Meetup 6

Demo

Page 51: Angular 2 Migration - JHipster Meetup 6

Questions ?