Pato Vargas

Software Engineer @ThisDot

pato_codes

devpato

Enterprise Angular App

Type

E-V-E-R-Y  T-H-I-N-G

pato_codes

Typescript Entities

  • classes
  • enums
  • interfaces (and types)

pato_codes

NEVER USE ANY

tasks$: Observable<Task[]>;
tasks$: any;
tasks$: Observable<any[]>;

DO IT

DON'T IT 

pato_codes

Angular Entities

modules, components, directives, services, pipes, and guards

SearchComponent we want to its files search.component.ts, search.component.html and search.component.scss

You can achieve this by using the Angular CLI

pato_codes

Feature Modules

pato_codes

Shared Code

2 kinds

App Shared Code

Projects Shared Code

pato_codes

App Shared Code

pato_codes

Projects Shared Code

NPM Enterprise Registry

pato_codes

Wait what!!

pato_codes

Libraries, Monorepos and Microfrontends

pato_codes

Angular Libraries

Where search-lib is the name of your library

ng generate library search-lib

pato_codes

Angular Libraries

PROS

  • We need to think and build these modules with reusability in mind.
  • Publish and share these libraries with other teams or projects.

pato_codes

Angular Libraries

CONS

  • Link your library to your main project and rebuild it for every change.
  • You will need to keep syncing your project with the latest version of the library.

pato_codes

Angular Monorepos

Monorepos are a source control pattern where essentially all the codebase lives in the same repository. All projects will always use the latest version of the code.

What is a Monorepo?

pato_codes

Angular Monorepos

  • Same library version for every app.
  • Ease of maintenance: when you update a shared library, you update it for all apps.
  • No conflicts between versions.

PROS

Angular Microservices

microfrontend allows large applications to be split into smaller apps in their own codebase, maybe using a totally different stack, that can be composed. For example, your search component could be written in Angular and the rest of the app in Polymer and React.

pato_codes

Where should I build my libraries?

  • All developers of a company are set to work on the same main project, no matter how large, use a monorepo.
  • If developers are set to work on different projects, teams, locations, and codebases, you may want to build each library in their own repository.

Be careful when using libraries

  • Every shared lib needs to have its own CI/CD pipeline.
  • Each CI/CD pipeline should handle versioning of changes.
  • Every time a new change happens in a shared repo, you need to go to all your projects using this library and update their npm packages.
  • There can be mismatches with different npm packages for angular projects.
  • In general, harder to do a cross-cutting change across multiple apps and libs as these are all in their own repository.

pato_codes

Tool for Enterprise

pato_codes

Getting started with Nx

npm install -g @nrwl/schematics
npx create-nx-workspace@latest thisdot

Install Nx globally

Create a Nx Workspace

pato_codes

Create an Nx Workspace

? What to create in the new workspace (Use arrow keys)
❯ empty             [an empty workspace] 
  web components    [a workspace with a single app built using web components] 
  angular           [a workspace with a single Angular application] 
  angular-nest      [a workspace with a full stack application (Angular + Nest)]
 
  react             [a workspace with a single React application] 
  react-express     [a workspace with a full stack application (React + Express)

pato_codes

Create a Nx Workspace

? What to create in the new workspace empty             [an empty workspace]
? CLI to power the Nx workspace       (Use arrow keys)
❯ Nx           [Extensible CLI for JavaScript and TypeScript applications] 
  Angular CLI  [Extensible CLI for Angular applications. Recommended for Angular
 projects.] 

pato_codes

Nx Workspace structure

Angular apps go here

Libraries used by your Angular apps go here

pato_codes

Creating an App

Add the capability to create Angular applications via:

ng add @nrwl/angular --defaults

Now create your Angular app

ng g @nrwl/angular:application employees

pato_codes

Creating an App

? Which stylesheet format would you like to use? 
  CSS 
❯ SASS(.scss)  [ http://sass-lang.com   ] 
  Stylus(.styl)[ http://stylus-lang.com ] 
  LESS         [ http://lesscss.org     ] 
? Would you like to configure routing for this application? (y/N) y

pato_codes

Project structure

pato_codes

Serve Angular App

ng serve employees

pato_codes

Getting started with Nx

pato_codes

Employee's Interface

In your command line

ng g @nrwl/workspace:lib employee

Go to libs/data/src/lib/employee.ts

export interface Employee {
  id: number;
  name: string;
}

pato_codes

Using our Interface

import { Employee } from '@thisdot/employee';

Note: If you are using VS Code, restart it

pato_codes

Creating a UI Library

ng g @nrwl/angular:lib ui

pato_codes

ui.module.ts

libs/ui/src/lib/ui.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  imports: [CommonModule]
})
export class UiModule {}

pato_codes

Component in our Library

ng g component employee-list --project=ui --export

pato_codes

employee-list.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { Employee } from '@thisdot/employee';
@Component({
  selector: 'thisdot-employee-list',
  templateUrl: './employee-list.component.html',
  styleUrls: ['./employee-list.component.scss']
})
export class EmployeeListComponent implements OnInit {
  @Input() employees: Employee[];
  constructor() { }

  ngOnInit() {}

  trackById(employee: Employee) {
    return employee ? employee.id : null;
  }
}

pato_codes

employee-list.component.html

<ul>
  <li *ngFor="let e of employees; trackBy: trackById(e)">{{ e.name }}</li>
</ul>

pato_codes

Creating a Service

ng g s employee --project=ui
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Employee } from '@thisdot/employee';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class EmployeeService {
  employees$: Observable<Employee[]>;
  constructor(private http: HttpClient) {
    this.employees$ = this.http.get<Employee[]>(
      'https://my-json-server.typicode.com/devpato/nx-fake-data/employees'
    );
  }
}

pato_codes

Service file

pato_codes

index.ts file

export * from './lib/ui.module';
export * from './lib/employee.service';

pato_codes

ui.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { EmployeeListComponent } from './employee-list/employee-list.component';

@NgModule({
  imports: [CommonModule, HttpClientModule],
  declarations: [EmployeeListComponent],
  exports: [EmployeeListComponent]
})
export class UiModule {}

pato_codes

Time to use

our UI Library

pato_codes

UI Libray

apps/employees/src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { UiModule } from '@thisdot/ui';

@NgModule({
  declarations: [AppComponent],
  imports: [
    UiModule,
    HttpClientModule,
    BrowserModule,
    RouterModule.forRoot([], { initialNavigation: 'enabled' })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

pato_codes

app.component.html

<div class="employees-container">
  <img src="../assets/images/logotdm.png" />
  <h1>Employees</h1>
  <thisdot-employee-list 
  [employees]="employeeService.employees$ | async">
  </thisdot-employee-list>
</div>

pato_codes

app.component.ts

import { Component } from '@angular/core';
import { EmployeeService } from '@thisdot/ui';

@Component({
  selector: 'thisdot-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor(private employeeService: EmployeeService) {}
}

pato_codes

app.component.scss

.employees-container {
  display: flex;
  width: 100%;
  height: 100vh;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  img {
    width: 200px;
  }
}

pato_codes

Share assets

pato_codes

Share assets

"assets": [
             "apps/employees/src/favicon.ico",
              "apps/employees/src/assets",
            {
              "glob": "**/*",
              "input": "./libs/ui/src/lib/shared-assets",
              "output": "./assets"
            }
          ]

pato_codes

RESTAR VS CODE

ng serve employees

pato_codes

Time to test our App!

pato_codes

You should see this

pato_codes

pato_codes

RxJS

pato_codes

RxJS

  • Declarative approach.
  • Think reactive.
  • RxJS is your friend.

pato_codes

RxJS Declarative Approach

  • leverage the power of rxjs observables and operators.
  • effectively combine streams.

 

  • easy share observables.
  • readily react to user action.

pato_codes

RxJS Declarative Approach

  products$ = this.http.get<Product[]>(this.productsUrl)
    .pipe(
      tap(data => console.log('Products', JSON.stringify(data))),
      catchError(this.handleError)
    );

  // Combine products with categories
  // Map to the revised shape.
  productsWithCategory$ = combineLatest([
    this.products$,
    this.productCategoryService.productCategories$
  ]).pipe(
    map(([products, categories]) =>
      products.map(product => ({
        ...product,
        price: product.price * 1.5,
        category: categories.find(c => product.categoryId === c.id).name,
        searchKey: [product.productName]
      }) as Product)
    ),
    shareReplay(1)
  );

pato_codes

NgRx

pato_codes

Other tools to manage the state

pato_codes

State management

pato_codes

SASS

https://slides.com/patriciovargas/sass/fullscreen

pato_codes

Other things to consider

  • NGFOR TRACKBY

  • SUBSCRIBE IN THE VIEW

  • ONPUSH CHANGE DETECTION

  • AOT COMPILER

  • LAZY LAODING

pato_codes

Complete Project

pato_codes

Conclusion

pato_codes

Special Thanks To

-This Dot Labs

-The Nrwl Team for Nx
-FrontEnd Consulting
-Christian Ludman
-Bálint Mérő

pato_codes

Brought to you by

ThisDotMedia

ThisDotLab

Enterprise Angular

By Patricio Vargas

Enterprise Angular

  • 151