WU Upgrade Guide
NG2.0 - TS2.0
Changes
- Angular 2.0 stable
- Typescript 2.0 stable
- Providers strategy
- Unit tests strategy
Angular
@NgModule
- Should be in index.ts
- We'll have one NgModule per base directory.
- All declarables from that folder should be in that module.
- Export only what's necessary for others.
- Import everything you need, even CommonModule
// lib imports
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
// external imports
import {WuTopCitiesModule} from 'shared/wu-top-cities';
import {WuDisplayUnitModule} from 'shared/wu-display-unit';
import {LazyLoadComponent} from 'helpers/lazy-load-component';
// internal imports
import {WuFavorites} from './wu-favorites';
import {WuFavoritesBar} from './wu-favorites-bar';
import {WuFavoritesMore} from './wu-favorites-more';
import {WuFavoritesShowMore} from './wu-favorites-show-more';
// exports
export * from './globals';
@NgModule({
imports: [
CommonModule,
WuTopCitiesModule,
WuDisplayUnitModule
],
providers: [
{provide: LazyLoadComponent, useValue: WuFavorites}
],
declarations: [
WuFavorites,
WuFavoritesBar,
WuFavoritesMore,
WuFavoritesShowMore
],
entryComponents: [
WuFavorites
]
})
export class WuFavoritesModule {}
@NgModule Fields
-
imports
- All the external modules that our code makes reference to
-
providers
- All the custom providers for our module. Providers in here will create a new instance, so we'll only provide local/internal services in here
-
declarations
- All the components, directives and pipes defined by our module
@NgModule Fields
-
exports
- All the declarations we want to share with other modules
-
entryComponents
- Components that might be an entry point of the app
-
bootstrap (don't use)
- Components we want angular bootstrap for us. We have another strategy for this
Index Structure
header comment
lib imports
external imports
internal imports
exports & re-exports
ngModule
/**
* @module WuFavorites
* @preferred
* @author Diego Barahona
* @since 4/12/16
*/ /** */
// lib imports
import {NgModule} from '@angular/core';
// external imports
import {..} from '...';
// internal imports
import {...} from './...';
// exports
export * from './globals';
@NgModule({...})
export class WuFavoritesModule {}
Lazy Load
We have to use a custom setup for lazy load components into the page. This is why we don't use bootstrap.
import {LazyLoadComponent} from 'helpers/lazy-load-component';
...
@NgModule({
...
providers: [
{provide: LazyLoadComponent, useValue: WuFavorites}
],
...
})
export class WuFavoritesModule {}
@Component
Components no longer declare have the directives or pipes fields, and we use @NgModule for the providers.
// lib imports
import {Component} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'wu-favorites',
templateUrl: './wu-favorites.html'
})
export class WuFavorites {...}
Prepare for AoT
Whit AoT compile and server side rendering we need some rules:
- Make public any property/method used in a template
- Ng hook methods need to be declared with all the necesary parameters
export class WuFavorites implements OnChanges {
// All needed variables for the template
public favorites: any;
public popular: any;
public recents: any;
public cities: any;
public ngOnChanges(changes: SimpleChanges): void {...}
}
Typescript
Changes
- Path aliases
- Strict Null Check
Path Aliases
We have now aliases to avoid long & ugly imports.
- "components/*" => "src/components/*/index"
- "components/*/globals" => "src/components/*/globals"
- "shared/*" => "src/shared/*/index"
- "shared/*/globals" => "src/shared/*/globals"
- "helpers/*" => "src/helpers/*/index"
- "testing/*" => "src/testing/*/index"
- "testing" => "src/testing/index"
Path Aliases
// src/herlpers/globals/index.ts
import {mergeGlobals} from 'helpers/globals';
// src/testing/index.ts
import {TestComponentBuilderFactory} from 'testing';
// src/shared/wu-top-cities/index.ts
import {WuTopCitiesModule} from 'shared/wu-top-cities';
// src/shared/wu-top-cities/globals.ts
import {WuTopCitiesGlobals} from 'shared/wu-top-cities/globals';
Strict Null Check
It's better to read about this in the documentation.
// WRONG
// error, string is not ensured to be returned
// actual type is string|undefined
function Test(value: boolean): string {
if (value) {
return 'test';
}
}
// error, value is not ensured to exist
// actual type is string|undefined
function Test2(value?: string): string {
return value.replace('-', '');
}
// CORRECT
function Test(value: boolean): string|undefined {
if (value) {
return 'test';
}
}
function Test2(value?: string): string {
if (value) {
// now value is type string
return value.replace('-', '');
} else {
return '';
}
}
Globals
(Providers)
Globals File
We're not using the old export const at the end of the file. Instead we're using a proper file for it.
We call it globals because now we're not only dealing with providers, but with modules as well.
/**
* @module WuCache
*/ /** */
// lib imports
import {JsonpModule} from '@angular/http';
// external imports
import {mergeGlobals} from 'helpers/globals';
import {WuQueryGlobals} from 'shared/wu-query/globals';
import {WuCacheGlobals} from 'shared/wu-cache/globals';
// internal imports
import {WuApiService} from './wu-api.service';
import {WuUrlGenerator} from './wu-url-generator';
export const WuApiGlobals = mergeGlobals({
providers: [
WuApiService,
WuUrlGenerator
],
imports: [
JsonpModule
]
}, [
WuCacheGlobals,
WuQueryGlobals
]);
/**
* @module WuAds
*/ /** */
// external imports
import {mergeGlobals} from 'helpers/globals';
// internal imports
import {WuAdsService} from './wu-ads';
export const WuAdsGlobals = mergeGlobals({
providers: [
WuAdsService
]
});
/**
* @module WuSearchAutocomplete
* @author Diego Barahona
* @since 2/9/16
*/ /** */
// external imports
import {mergeGlobals} from 'helpers/globals';
import {WuApiGlobals} from 'shared/wu-api/globals';
import {WuQueryGlobals} from 'shared/wu-query/globals';
import {WuTopCitiesGlobals} from 'shared/wu-top-cities/globals';
import {WuGeolocationGlobals} from 'shared/wu-geolocation/globals';
import {WuUserProfileGlobals} from 'shared/wu-user-profile/globals';
export const WuSearchGlobals = mergeGlobals({}, [
WuApiGlobals,
WuQueryGlobals,
WuTopCitiesGlobals,
WuGeolocationGlobals,
WuUserProfileGlobals
]);
Unit-Tests
It actually works with the same TestComponentBuilder but with some modifications.
Options now accept a preCompileHook, which is a function to be called before compile all the modules.
Also a globals and modules array to be provided with what you need.
@Component({
moduleId: module.id,
templateUrl: './template.html'
})
class TestComponent {
@ViewChild(WuBlogFeatured)
public wuBlogFeatured: WuBlogFeatured;
public blog = Jeffblog;
}
@NgModule({
imports: [WuNewsModule],
declarations: [TestComponent]
})
class TestModule {}
const myOptions = new TestComponentOptions();
myOptions.modules = [TestModule];
myOptions.globals = [WuNewsGlobals];
myOptions.preCompileHook = () => {
TestBed.overrideModule(WuNewsModule, {
add: {exports: [WuBlogFeatured]}
});
};
deck
By Diego Barahona
deck
- 637