Always commit your yarn.lock file into the source code repo

I use the Yarn package manager for all my Angular projects. Besides being faster than npm, yarn creates a file yarn.lock that stores the exact versions of installed dependencies. Last year, I wrote about a specific use case that caused a breaking change during one of my Angular workshops.

Yesterday, I had to create a new project using Angular CLI. The project was successfully generated and started with ng serve. Then, I wanted to create a production build with ng build –prod, but the build failed with the error Cannot find module ‘uglifyjs-webpack-plugin’. I know that Webpack uses UglifyJS for optimizing sizes of the bundles, which is great, but my production build fails, which is not great at all.

The generated package.json file located in the root of my project has no direct dependency on uglifyjs-webpack-plugin, but there is one deep inside node_modules in one of the thousand (literally) dependencies used in Angular CLI projects.

To make the long story short, the WebPack team pushed to npmjs.org the new version 1.1.7 this plugin, which was empty. The Angular team got in touch with them, and an hour later, the fixed version 1.1.8 of the Webpack UglifyJS plugin was pushed to the npm central repo.

My project already had the yarn.lock file with an erroneous version of this plugin. I deleted it and ran yarn install again. This time it picked up the fixed 1.1.8 version and the ng build –prod command started working again. Thank you, the Webpack team for the quick turnaround! Happy end!

This was a specific issue with the newly generated project created at the “wrong time”. But imagine a team working on a project for some time, and their github repo didn’t include the yarn.lock file that stored the reference to the working version 1.1.6 of that plugin, and Mary (the QA engineer) decided to make a production build. A minute later, the entire team got an email titled “Who broke the build?”

The bottom line: Push the yarn.lock of the project that works and builds correctly into your version control system to ensure that the entire team has a reproducible and working build. This way, your project won’t depend on someone from across the globe submitting erroneous packages to the npmjs.org.

P.S. While npm 5 also creates the file package-lock.json with the registry of all installed dependencies, it doesn’t guarantee that each npm install will install exact versions of the packages listed there.

Advertisements

Creating an Angular app that weighs only 55KB

With Angular CLI, generating a new app and installing dependencies takes 30 seconds. Creating a production build takes another 15 seconds. And the best part is that the size of the deployed app can be as small as 55KB gzipped. Let’s do it.

1. Generate a minimalistic app with the inline template and styles with the following Angular CLI command:

ng new hello-world --minimal

2. If you’re not creating custom decorators and perform the AoT build, you don’t need to import the reflect polyfill, so comment out the following line in the generated file polyfills.ts:

import 'core-js/es7/reflect';

3. In the generated file app.component.ts remove most of the HTML markup from the component template so it looks as follows:

template: `Welcome to {{title}}!`

4. Make a production build (it performs the AoT compilation by default):

ng build -prod

5. The npm package serve is a small web server that can gzip static files on the fly. Install it globally:

npm install serve -g

6. Change to the dist directory where the application bundles were generated and serve the app (it’ll run on port 5000 by default):

serve .

7. Enjoy the small size!

To see it in action, watch this 5-minute video.

Update. Hello World in the upcoming rendering engine Ivy is only 3.3KB!
See https://ng-ivy-demo.firebaseapp.com/

Wrapping a RxJS observable stream into an Angular service

Angular’s dependency injection mechanism allows us to cleanly separate business logic (services) from UI (components). What if our app generates a stream of values and we want to implement it as an injectable service? In this blog, I’ll create an injectable service that emits a stream of values and a UI component subscribes to this stream displaying its values real time.

In one of my RxJS blogs  I showed you how to use the method Observable.create() providing an observer as an argument. Let’s create a service with a method that will take an observer as an argument and will emit the current time every second.

import {Observable} from 'rxjs/Observable';

export class ObservableService{

  createObservableService(): Observable<Date>{  // 1

      return new Observable(  // 2
          observer => {   // 3
              setInterval(() =>
                  observer.next(new Date())  // 4
              , 1000);
          }
      );
  }
}

1. Return an observable stream of dates
2. Create an observable
2. Provide an observer
4. Emit the new date every second

In this service, we create an instance of the RxJS Observable object, assuming that the subscriber will provide an Observer that knows what to do with the emitted data. Whenever the observable invokes the method next(new Date()) on the observer, the subscriber will receive the current date and time. Our data stream never throws an error and never completes.

We’ll inject the ObservableService into the AppComponent, which invokes the method createObservableService() and subscribes to its stream of values, creating an observer that knows what to do with the data. The observer just assigns the received time to the variable currentTime which renders the time on UI.

import 'rxjs/add/operator/map';
import {Component} from "@angular/core";
import {ObservableService} from "./observable.service";

@Component({
  selector: 'app-root',
  providers: [ ObservableService ],
  template: `<h1>Custom observable service</h1>
       Current time: {{currentTime | date: 'mediumTime'}}  // 1
  `})
export class AppComponent {

  currentTime: Date;

  constructor(private observableService: ObservableService) { // 2

    this.observableService.createObservableService()  // 3
      .subscribe( data => this.currentTime = data );  // 4
  }
}

1. Display the time using the date pipe
2. Inject the service that wraps the observable
3. Create the observable and start emitting dates
4. Subscribe to the stream of dates

This app doesn’t use any servers, and you can see it in action in the great Stackblitz online IDE  here.

In the browser’s window, the current time will be updated every second. You use DatePipe here with the format ‘mediumTime’, which displays only hours, minutes, and seconds (all date formats are described in the DatePipe documentation).

This simple example demonstrates a basic technique for wrapping any application logic in an observable stream and subscribing to it. In this case, we use setInterval(), but you could replace it with any application-specific code that generates one or more values and sends them as a stream.

Don’t forget about error handling and completing the stream if need be. The following code snippet shows a sample observable that sends one element to the observer, may throw an error and tells the observer that the streaming is complete:

return new Observable(
    observer => {
      try {
        observer.next('Hello from observable');

        //throw ("Got an error");

      } catch(err) {
         observer.error(err);
      } finally{
         observer.complete();
      }
    }
);

If you uncomment the line with a throw, observer.error() is invoked, which results in the invocation of the error handler on the subscriber if there is one.

The data producer for our observable stream was generating date/time but it could be any app code that generates some useful values, e.g. a WebSocket server generating stock quotes, auction bids, actions of online game players, etc. During my workshops, I show a sample online auction app that has a Node server emulating users’ bids on products. That server uses a WebSocket connection to push new bids for products to all users that are interested in receiving them.

Offline generation of Angular CLI projects with Yarn

There are situations when an ability to generate new Angular CLI projects from the locally installed packages is quite useful, for example:

  • You’re running a live workshop at a conference in a hotel and the students have to install project dependencies multiple times. When 20-30 people are installing Angular dependencies at the same time on a hotel’s connection, it can take three minutes or more.
  • You’re on a long flight and want to try something new with Angular.

In this post, I’ll show you how to generate Angular CLI projects in a disconnected mode.

First of all, I don’t use npm. I use Yarn for two main reasons:

  1. Yarn is faster than npm (including npm 5).
  2.  Yarn creates a file yarn.lock that keeps track of the exact version of packages installed.

For example, if package.json has a dependency “@angular/core”: “^5.0.0”, running yarn install today would include the version of 5.1.0 of this package. If you want to make sure that all devs in your team use this version even after 5.2.0 is available, push yarn.lock in the source control repo, and everyone who pulls the code will get 5.1.0. Reproducible builds are guaranteed. While npm 5 also creates a file package-lock.json, it doesn’t guarantee the same versions for all developers.

To configure Yarn as a default package manager for Angular CLI, run the following command:

ng set --global packageManager=yarn

Now let’s see how to create a local directory (a.k.a yarn offline mirror) with cached packages so Yarn can use it without the need to connect to the Internet.

Perform the following steps before boarding the plane while the Internet connection is still available.

1. Configure a directory for locally cached packages by running this command:

yarn config set yarn-offline-mirror ~/npm-packages-offline-cache

This will create a file .yarnrc in the user’s directory on your computer. In my case (I use MAC OS), this command creates the file .yarnrc with the following content

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


lastUpdateCheck 1512857190418
yarn-offline-mirror "/Users/yfain11/npm-packages-offline-cache"

2. Generate a new project with Angular CLI without installing dependencies:

ng new hello-cli --skip-install

3. Copy the file .yarnrc into the newly generated directory hello-cli

4. Change directory to hello-cli:

cd hello-cli

5. Install the project dependencies using Yarn:

yarn install

Important: Make sure that there is no file yarn.lock in hello-cli when you run this command for the first time.

This command not only will install dependencies in the node_modules directory but will also create a directory npm-packages-offline-cache in your user’s directory. This directory will contain about a thousand of compressed package files required for the offline installation. These are gzipped files with extension .tgz. This is your Yarn offline mirror with npm packages.

6. Just in case, clear the existing yarn cache to make sure we’ll be using only the files from the mirror:

yarn cache clean

Now let’s board the plane. Turn off the wi-fi or unplug the network wire. Our aircraft is airborne.

In the hello-cli directory, run the following command:

yarn install --offline

Yarn will install all the dependencies from the offline mirror. Now you can create as many Angular CLI projects as you need without being connected:

1. Generate a new project:

ng new hello-cli2 --skip-install 

2. Copy the file .yarnrc into the hello-cli2 directory

3. Change to the project directory

cd hello-cli2

4. Run the offline installation of the project dependencies

yarn install --offline

Have a safe flight!

P.S. If you’re running a workshop, have a flash drive with the yarn offline miror directory and ask the participants to copy it into their user’s directories. Then they’d just need to run a command to create the .yarnrc file as explained in step 1.

RxJS Essentials. Part 7: Handling errors with the catch operator

In this article, I’ll show you aone of the RxJS operators for error handling – the catch() operator. The previous articles in this series include:

1. Basic Terms
2. Operators map, filter, and reduce
3. Using Observable.create()
4. Using RxJS Subject
5. The flatMap operator
6. The switchMap operator

The Reactive Manifesto declares that a reactive app should be resilient, which means that the app should implement the procedure to keep it alive in case of a failure. An observable can emit an error by invoking the error() function on the observer, but when the error() method is invoked, the stream completes.

A subscription to an observable ends if one of the following occurs:

1. The consumer explicitly unsubscribes
2. The observable invokes the complete() method on the observer
3. The observable invokes the error() method on the observer

RxJS offers several operators to intercept and handle the error before it reaches the code in the error() method on the observer.

* catch(error) – intercepts the error and you can implement some business logic to handle it
* retry(n) – retries the erroneous operation up to n times

* retryWhen(fn) – retries the erroneous operation as per the provided function

In this article, I’ll show you an example of using the catch() operator. Inside the catch() operator you can check the error status and react accordingly. The following code snippet shows how to intercept an error, and if the error status is 500, switch to a different data producer to get the cached data. If the received error status is not 500, this code will return an empty observable and the stream of data will complete. In any case, the method error() on the observer won’t be invoked.

.catch(err => {  
    console.error("Got " + err.status + ": " + err.description);

    if (err.status === 500){
        console.error(">>> Retrieving cached data");

        return getCachedData();  // failover
    } else{
      return Rx.Observable.empty();  // don't handle the error
    }
})

The following listing shows the complete example, where we subscribe to the stream of beers from a primary source – getData() – which randomly generates an error with the status 500. The catch() operator intercepts this error and switches to an alternative source – getCachedData().

function getData(){
    var beers = [
        {name: "Sam Adams", country: "USA", price: 8.50},
        {name: "Bud Light", country: "USA", price: 6.50},
        {name: "Brooklyn Lager", country: "USA", price: 8.00},
        {name: "Sapporo", country: "Japan", price: 7.50}
    ];

    return Rx.Observable.create( observer => {
        let counter = 0;
        beers.forEach( beer => {
                observer.next(beer);   // 1
                counter++;

                if (counter > Math.random()*5) {   // 2
                    observer.error({
                            status: 500,
                            description: "Beer stream error" 
                        });
                } 
            }
        );

        observer.complete();}
    );
}

// Subscribing to data from the primary source
getData() 
    .catch(err => {  // 3
        console.error("Got " + err.status + ": " + err.description);
        if (err.status === 500){
            console.error(">>> Retrieving cached data");
            return getCachedData();   // 4
        } else{
          return Rx.Observable.empty();  // 5  
        }
    })
    .map(beer => beer.name + ", " + beer.country)
    .subscribe(
        beer => console.log("Subscriber got " + beer),
        err => console.error(err),
        () => console.log("The stream is over")
    );

function getCachedData(){  // 6
    var beers = [
        {name: "Leffe Blonde", country: "Belgium", price: 9.50},
        {name: "Miller Lite", country: "USA", price: 8.50},
        {name: "Corona", country: "Mexico", price: 8.00},
        {name: "Asahi", country: "Japan", price: 7.50}
    ];

    return Rx.Observable.create( observer => {
        beers.forEach( beer => {
                observer.next(beer);
            }
        );

        observer.complete();}
    );
}

1. Emit the next beer from the primary data source
2. Randomly generate the error with the status 500
3. Intercept the error before it reaches the observer
4. Failover to the alternative data source
5. Don’t handle the non-500 errors; return an empty observable to complete the stream
6. The alternative data source for failover

The output of this program can look as follows:

Subscriber got Sam Adams, USA
Subscriber got Bud Light, USA
Got 500: Beer stream error
>>> Retrieving cached data
Subscriber got Leffe Blonde, Belgium
Subscriber got Miller Lite, USA
Subscriber got Corona, Mexico
Subscriber got Asahi, Japan
The stream is over

NOTE: To see it in CodePen, follow this link.

Update: With pipeable operators, use catchError instead of catch.

In the next article of this series, I’ll introduce you to the pipeable operators.

If you have an account at O’Reilly’s safaribooksonline.com, you can watch my video course “RxJS Essentials” there.

RxJS Essentials. Part 6: The switchMap operator

In this article I’ll introduce the switchMap() operator. The previous articles in this series include:

1. Basic Terms
2. Operators map, filter, and reduce
3. Using Observable.create()
4. Using RxJS Subject
5. The flatMap operator

In the previous article of this series, I demoed the use of flatMap(). While flatMap() unwraps and merges all the values emitted by the outer observable, the switchMap() operator handles the values from the outer observable but cancels the inner subscription being processed if the outer observable emits a new value. The switchMap() operator is easier to explain with the help of its marble diagram shown next.

The outer observable emits the red circle, and switchMap() emits the item from the inner observable (red diamond and square) into the output stream. The red circle was processed without any interruptions because the green circle was emitted after the inner observable finished processing.

The situation is different with the green circle. The switchMap() managed to unwrap and emit the green diamond, but the blue circle arrived before the green square was processed. So the subscription to the green inner observable was cancelled, and the green square was never emitted into the output stream. In other words, the switchMap() operator switched from processing of the green inner observable to the blue one.

The following example has two observables. The outer observable uses the function interval() and emits a sequential number every second. With the help of the take() operator, we limit the emission to two values: 0 and 1. Each of these values is given to the switchMap() operator, and the inner observable emits three numbers with the interval of 400 milliseconds.

let outer$ = Rx.Observable
               .interval(1000)
               .take(2);

let combined$ = outer$.switchMap((x) => {  
     return Rx.Observable
	          .interval(400)
	          .take(3)
	          .map(y => `outer ${x}: inner ${y}`)
});

combined$.subscribe(result => console.log(`${result}`));

The output of this script is shown next:

outer 0: inner 0
outer 0: inner 1
outer 1: inner 0
outer 1: inner 1
outer 1: inner 2

Note that the first inner observable didn’t emit its third value 2. Here’s the timeline:

1. The outer observable emits zero and the inner emits zero 400 milliseconds later
2. In 800 milliseconds later, the inner observable emits 1
3. In 1000 milliseconds the outer observable emits 1, and inner observable was unsubscribed
4. The three inner emissions for the second outer value went uninterrupted because it didn’t emit any new values

If you replace flatMap() with switchMap() the inner observable will emit three values for each outer value as shown below.

outer 0: inner 0
outer 0: inner 1
outer 0: inner 2
outer 1: inner 0
outer 1: inner 1
outer 1: inner 2

NOTE: To see it in CodePen, follow this link.

The chances are slim that you’ll be writing outer and inner observables emitting integers but there are various practical use cases for switchMap(). For example, in my Angular apps (Angular comes with RxJS) I use switchMap() with the HttpClient object (it returns observable) to discard the results of the unwanted HTTP requests. Just think of a user that types in an HTML input field (the outer observable) and the HTTP requests are being made (inner observable) on each keyup event. The circles on the diagram are the three characters that the user is typing. The inner observables are HTTP requests issued for each character. If the user entered the third character but the HTTP request for the second one is still pending, the inner observable for the second character gets cancelled and discarded so the browser will never recieve the HTTP response.

TIP. The function interval() is handy if you want to invoke another function periodically based on the specified time interval. For example, myObservable.interval(1000).subscribe(n => doSometing()) will result in calling the function doSomething() every second.

NOTE: If your code has nested subscribe() calls, this should be a red flag to you. Consider re-writing this code using flatMap(), switchMap(), or concatMap().

If you have an account at O’Reilly’s safaribooksonline.com, you can watch my video course “RxJS Essentials” there.

In the next article, I’ll show how to intercept errors from an observable stream with the catch(operator.)

RxJS Essentials. Part 5: The flatMap operator

In this article I’ll introduce an RxJS flatMap() operator. Previous articles in this series include:

1. Basic Terms
2. Operators map, filter, and reduce
3. Using Observable.create()
4. Using RxJS Subject

In some cases, you need to treat each item emitted by an observable as another observable. In other words, the outer observable emits the inner observables. Does it mean that we need to write nested subscribe() calls (one for the outer observable and another for the inner one)? No, we don’t. The flatMap() operator takes each item from the outer observable and auto-subscribes to it.

Some operators are not explained well in RxJS documentation, and we recommend you to refer to the general ReaciveX (reactive extensions) documentation for clarification. The flatMap() operator is better explained there, and it states that flatMap() is used to “transform the items emitted by an observable into observables, then flatten the emissions from those into a single observable”. This documentation includes the following marble diagram:

As you see, the flatMap() operator takes an emitted item from the outer observable (the circle) and unwraps its content (the inner observable of diamonds) into the flattened output observable stream. The flatMap() operator merges the emissions of the inner observables so their items may interleave.

The following code listing has an observable that emits drinks, but this time it emits not individual drinks, but palettes. The first palette has beers and the second – soft drinks. Each palette is observable. We want to turn these two palettes into an output observable with individual beverages.

function getDrinks() {

    let beers = Rx.Observable.from([   // 1
        {name: "Stella", country: "Belgium", price: 9.50},
        {name: "Sam Adams", country: "USA", price: 8.50},
        {name: "Bud Light", country: "USA", price: 6.50}
    ], Rx.Scheduler.async);

    let softDrinks = Rx.Observable.from([    // 2
        {name: "Coca Cola", country: "USA", price: 1.50},
        {name: "Fanta", country: "USA", price: 1.50},
        {name: "Lemonade", country: "France", price: 2.50}
    ], Rx.Scheduler.async);

    return Rx.Observable.create( observer => {
            observer.next(beers);     // 3
            observer.next(softDrinks);   // 4
            observer.complete();
        }
    );
}

// We want to "unload" each palette and print each drink info

getDrinks()
  .flatMap(drinks => drinks)    // 5   
  .subscribe(  // 6
      drink => console.log("Subscriber got " + drink.name + ": " + drink.price ),
      error => console.err(error),
      () => console.log("The stream of drinks is over")
  );

1. Creating an async observable from beers
2. Creating an async observable from soft drinks
3. Emitting the beers observable with next()
4. Emitting the soft drinks observable with next()
5. Unloading drinks from pallets into a merged observable
6. Subscribing to the merged observable

This script will produce the output that may look as follows (note that the drinks interleave):

Subscriber got Stella: 9.5
Subscriber got Coca Cola: 1.5
Subscriber got Sam Adams: 8.5
Subscriber got Fanta: 1.5
Subscriber got Bud Light: 6.5
Subscriber got Lemonade: 2.5
The stream of observables is over

To see it in CodePen visit this link.

Are there any other uses of the flatMap() operator besides unloading palettes of drinks? Another scenario where you’d want to use flatMap() is when you need to execute more than one HTTP request, where the result of the first request should be given to the second one. In Angular, HTTP requests return observables and without flatMap() this could be done (it a bad style) with nested subscribe() calls:

this.httpClient.get('/customers/123')
  .subscribe(customer => {
              this.httpClient.get(customer.orderUrl)
              .subscribe(response => this.order = response)
  })

The method httpClient.get() returns an observable, and the better way to write the above code is by using the flatMap() operator, which auto-subscribes and unwraps the content of the first observable and makes another HTTP request:

httpClient.get('./customers/123')
          .flatMap(customer => this.httpClient.get(customer.orderURL))
          .subscribe(response => this.order = response);

Since a flatMap() is a special case of map(), you can specify a transforming function while flattening the observables into a common stream. In the above example, we transform the value customer into a function call httpClient.get().

TIP: In RxJS, flatMap() is an alias of mergeMap() so these two operators have the same functionality.

Let’s consider one more example of using flatMap(). This example will be a modified version of the traders-orders example used in the article “Using RxJS Subject“. This example is written in TypeScript and it uses two Subject instances:

* traders – this Subject keeps track of traders
* orders – this Subject is declared inside the class Trader and keeps track of each order placed by a particular trader.

You’re the manager who wants to monitor all orders placed by all traders. Without flatMap(), you’d need to subscribe to traders (the outer observable) and create a nested subscription for orders (the inner observable) that each subject has. Using flatMap() allows you to write just one subscribe() call, which will be receiving the inner observables from each trader in one stream.

import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/mergeMap';

enum Action{
    Buy = 'BUY',
    Sell = 'SELL'
}

class Order{
    constructor(public orderId: number, public traderId: number, public stock: string, public shares: number, public action:Action){}
}

let traders = new Subject<Trader>();  // 1

class Trader {

    orders = new Subject<Order>();   // 2

    constructor(private traderId:number, public traderName:string){}
}

let tradersSubscriber = traders.subscribe(trader => console.log(`Trader ${trader.traderName} arrived`))

let ordersSubscriber = traders        // 3
  .flatMap(trader => trader.orders)   // 4
  .subscribe(ord =>      // 5
       console.log(`Got order from trader ${ord.traderId} to ${ord.action} ${ord.shares} shares of ${ord.stock}`));

let firstTrader = new Trader(1, 'Joe');
let secondTrader = new Trader(2, 'Mary');

traders.next(firstTrader);
traders.next(secondTrader);

let order1 = new Order(1, 1,'IBM',100,Action.Buy);
let order2 = new Order(2, 1,'AAPL',200,Action.Sell);
let order3 = new Order(3, 2,'MSFT',500,Action.Buy);

// Traders place orders
firstTrader.orders.next( order1);
firstTrader.orders.next( order2);
secondTrader.orders.next( order3);

1. Declare the Subject for traders
2. Each trader has its own Subject for orders
3. Starting with the outer observable traders
4. Extracting the inner observable from each Trader instance
5. The function subscribe() receives a stream of orders

In this version of the program, the class Trader doesn’t have a method placeOrder(). We just have the trader’s observable orders push the order to its observer by using the method next(). Remember, a Subject has both observable and observer.

The output of this program is shown next.

Trader Joe arrived
Trader Mary arrived
Got order from trader 1 to BUY 100 shares of IBM
Got order from trader 1 to SELL 200 shares of AAPL
Got order from trader 2 to BUY 500 shares of MSFT

In our example, the subscriber just prints the orders on the console, but in a real world app it could invoke another function that would be placing orders with the stock exchange for execution.

To see it in CodePen, follow this link. In the next article you’ll learn about a very useful operator switchMap().

If you have an account at O’Reilly’s safaribooksonline.com, you can watch my video course “RxJS Essentials” there.