Yarn package manager: yarn.lock

Yesterday, I was running yet another Angular workshop. After explaining how to install dependencies using npm, I show how to use Yarn (see this blog), a faster alternative to npm, and suggest that the students should consider using Yarn.

Before the workshop, I give handouts with several projects to the group and then ask the group to open a particular project, install the dependencies and run the app. Usually, everything goes smoothly, but this time many people started to complain about a runtime error. In this app, I was using themes from Angular Material 2, but the app couldn’t find the file “node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css”.

I was strange. I tested all the projects two days before the class. After checking the content of the node_modules directory on Paul’s computer, I couldn’t find even the directory node_modules/@angular/material/core let alone that CSS file.

Then I asked if everyone gets this error? Everyone except Jim got this error. Jim was using Yarn for installing dependencies while everyone else was using npm. After learning this, I guessed what was the problem.

I’ using Yarn too, and all my projects included the file yarn.lock, which is created after the initial install storing all packages and their versions there were installed for the project. When you do the yarn install next time, it checks if the file yarn.lock is present, it installs exactly packages of those versions that were listed in yarn.lock. This file can be checked into the version control repo used by your team to ensure that everyone would have exactly the same dependencies.

Now let me explain what happened in the classroom. The package.json in that project included the dependency

"@angular/material": "^2.0.0-beta.2"

The file yarn.lock in that project had the following:

"@angular/material@^2.0.0-beta.2":
  version "2.0.0-beta.2"
  resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.2.tgz#65ee8733990347b7518b7f42113e02e069dc109b"

Hence, when Jim ran his Yarn install, he got Angular Material 2 2.0.0-beta.2, which had the file “node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css”

But last week, a new version (Beta.3) of Angular Material 2 has been released with a breaking change – they rearranged the file structure:

So the students who didn’t use Yarn, got the latest version while my project used “the old” location of that CSS file.

Fixing this issue in the app was an easy task, but I wanted you to appreciate that Yarn gives you predictability in the projects that have multiple dependencies. Some library author introduces a breaking change, and your app gives a runtime error.

After fixing the CSS location in the app, I deleted my yarn.lock file and re-ran the install. The newly created yarn.lock has this fragment:

"@angular/material@^2.0.0-beta.2":
  version "2.0.0-beta.3"
  resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.3.tgz#ec31dee61d7300ece28fee476852db236ded1e13"

The first line indicates the dependency as it was listed in my package.json, and the second line shows the actual version that has been installed. Now my project is working again… until the next breaking change.

Angular CLI: multiple apps in the same project

You may need to have an Angular project that has multiple apps so you can run the build of a particular app, say depending on the customer you’re preparing the build for. In my case, I wanted to create a project with multiple apps that I use in my Angular workshops. Having a single project with multiple apps allows you to run a time-consuming npm or yarn install once and just modify the name of the app you want to run.

For example, you may have multiple versions of the main bootstrap file that load different root modules. The file .angular-cli.json has the apps section with the property main, and to run a particular app, I’d instruct the students to modify .angular-cli.json to point at a particular app, e.g. "main": "main1.ts". To run another app, I’d instruct them to change this line to "main": "main2.ts".

But then I figured out that you can configure multiple apps in the same .angular-cli.json and run the build for a particular app by name. The apps property is an array, and you just need to configure each app there. For example, the following fragment shows how I configured two applications – app1 and app2 in the same .angular-cli.json:

"apps": [
    { "name":"app1",
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main-resolver.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.css",
       "../node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css"
      ],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    },
    { "name":"app2",
      "root": "src",
      "outDir": "dist2",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main-luxury.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.css",
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ],

Now to bootstrap the app main-resolver.ts I run the following command:

ng serve --app app1

To bootstrap the main-luxury.ts, I run this:

ng serve --app app2

You can also refer to each app by its index in the apps array:

ng serve --app 0
or
ng serve --app 1

The option –app is available for the ng build command as well. The following screen shot shows my project after I built the app1 into dist and app 2 into dist2.

This is a pretty useful Angular CLI feature and I wanted to share my findings with you.

Angular 4: Changes in the router

Angular 4 comes with some useful changes in the router. Let’s take a look at the changes in receiving parameters by a route and in the CanDeactivate guard (see here).

A route can receive the parameters either using a snapshot property of the ActivatedRoute or by subscribing to its property param. Now there is a property paramMap that allows you to either get a particular parameter by using the method get() or get all parameters by invoking getAll().

Here’s how to receive a parameter id that’s not changing in the parent:

export class ProductDetailComponentParam {
  productID: string;

  constructor(route: ActivatedRoute) {
    this.productID = route.snapshot.paramMap.get('id');
  }
}

If the parameter id is changing in the parent (as described here), you can subscribe to the stream of id’s as follows:

export class ProductDetailComponentParam {
  productID: string;

  constructor(route: ActivatedRoute) {

    route.paramMap.subscribe(
     params => this.productID = params.get('id')
     );
  }
}

The CanDeactivate guard now allows you to be more specific and conditionally prohibit navigating from a route depending on where the user is planning to navigate. The interface CanDeactivate now has an optional parameter nextState, which you can check to decide if you want to prohibit the navigation or not. The next code snippet shows the guard that would display a warning popup only if the user is trying to navigate to the home route represented by the path ‘/’. The navigation to any other routes remains unguarded.

@Injectable()
export class UnsavedChangesGuard implements CanDeactivate<ProductDetailComponent>{

    constructor(private _router:Router){}

    canDeactivate(component: ProductDetailComponent, 
                  currentRoute: ActivatedRouteSnapshot,
                  currentState: RouterStateSnapshot, 
                  nextState?: RouterStateSnapshot){

        let canLeave: boolean = true;

        // If the user wants to go to home component
        if (nextState.url === '/') {
          canLeave = window.confirm("You have unsaved changes. Still want to go home?");
        }
        return canLeave;

    }
}

Angular 4 was just released and there might be some other goodies in the router, but I just wanted to share with you these convenient additions.

Upgrading to the latest Angular CLI

As of the Angular CLI beta 30, the command to install Angular CLI looks as follows:

npm install -g @angular/cli

To get rid of the old version of Angular CLI and install the new one, run the following commands:

npm uninstall -g angular-cli
npm cache clean
npm install -g @angular/cli

To update the existing CLI projects, modify the CLI dev dependency in package.json to this:

"@angular/cli": "1.0.0-beta.32"

Then update the CLI version on top of the angular-cli.json, remove your node_modules dir and run npm install.

My upcoming speaking engagements

In the upcoming six months of 2017 I’ll be speaking at the following conferences:

1. BuzzJS, New York City, January 27, 1 talk

2. DevNexus, Atlanta, February 22-24, 2 talks

3. DevoxxUS, San Jose, March 21-23, 2 talks

4. Angular Summit, Chicago, May 10-11, 8 talks (my personal record!)

5. JEEConf, Kiev, Ukraine, May 26-27, TBD

6. JCrete, Crete, Greece, July 17-21, TBD

Hope to see you at one of these events!

Angular 2: What’s with the name?

The Angular 2 framework now supports semantic versioning, and it was announced that major upgrades (with breaking changes) will be released twice a year. In particular, in March of 2017 the version 4.0.0 will be released, in September – 5.0.0 and so on.

This is all good but the problem is that not only the versioning will be different, but Angular team is considering changing the name from Angular 2 to Angular. This will create lots of confusion in the Angular community.

First, a bit of history. The older version of this super popular Web framework is called AngularJS (currently at 1.6.0). Two years ago a complete redesign of this framework was announced, and the new framework got the name Angular 2. I guess, someone at Google suggested to keep the word Angular in the name to leverage the fact that more than 1.3 million of software developers were already using AngularJS, and most of these people would want to upgrade to the newer version of the same framework.

The problem is that Angular 2 is completely different framework, and suggesting the roadmap for upgrading existing AngularJS apps to Angular 2 is no different than suggesting a roadmap for upgrading an app from Ember or React to Angular 2. But the marketing plan worked out nicely, and more than 700K developers are using Angular 2 by now. No wonder – Angular 2 is a great framework.

People started creating Angular 2 communities to post articles, and ask for help. For example, the Reddit’s Angular 2 community is pretty active and has 6800 members: https://www.reddit.com/r/Angular2/. Questions and answers on StackOverflow are marked with the tag #angular2: http://stackoverflow.com/questions/tagged/angular2. LinkedIn has a group of 7900 Angular 2 developers: https://www.linkedin.com/groups/8434339.

Bloggers (myself included) are posting articles and tutorials that have Angular 2 in their names. PluralSight, Lynda.com, egghead.io and many independent developers produce video contend with Angular 2 in their titles.

Book authors (myself included) wrote about a dozen books with Angular 2 in their titles, and these books will remain relevant and useful for several years, unless Google will decide to completely re-write this framework again.

If the framework will be renamed to Angular, anyone searching for Angular 2 content will be inevitable getting materials for both AngularJS and Angular 2. Just try finding posts on StackOverflow tagged as Angular: http://stackoverflow.com/questions/tagged/angular. The “angular” in the URL will be automatically converted to “angularjs” and you’ll be seeing 200K+ irrelevant posts about AngularJS. IMO, it’s a disservice to the community. BTW, there is Angular Reddit group as well: https://www.reddit.com/r/angular, and these developers may want to keep their forum clean from Angular 2 posts.

I suggest to keep Angular 2 as the name of the framework. The digit 2 here won’t represent the version, but rather the next generation of this framework. So in March we’ll get Angular 2 v. 4.0.0, in September – Angular 2 v.5.0.0 and so on. Content producers can still include “Angular 2” in the titles and use the tag #angular2 in social networks.

What do you think?

P.S. The community may decide to keep using the tag #angular2 regardless of the official name of this framework.

A Web developer’s reading list

Manning is planning to release a free book sampler that would include chapters from different books covering modern Web development process. They asked me to select books/chapters and write a short intro, which I did and decided to share this with you.

The modern world of Web development requires software engineers who are well versed in multiple disciplines. Of course, familiarity with the JavaScript syntax is a must. As Atwood’s law states, “Any application that can be written in JavaScript, will eventually be written in JavaScript”. Well, maybe not in the pure JavaScript, but in its more productive superset called TypeScript.

Web developers use frameworks and/or libraries to avoid re-inventing the wheel while working on applications. While many people are still happy with jQuery, more progressive developers are debating: Angular or React? This comparison is wrong because React is a library while Angular is a framework with batteries included. But Angular and React are the most popular tools in the Web development ecosystem today.

There is a trend to develop applications using principles of reactive programming. The data consumer subscribes to the data stream that’s pushed to the consumer only when the data is available. This is an alternative to the polling model that requires the client to make periodic requests for data, which may or may not not be available. The RxJS library implements the push model via observable streams of data. This library offers you a variety of chainable operators (functions) that handle and transform the data en route.

Making your application available on mobile devices is important. Will your Web application look good on a small screen or you’d better create separate native applications for each mobile platform? There is is a third approach to create so called hybrid applications that run a Web container inside your mobile device translating HTML elements into their native counterparts. Actually there is a forth approach that suggests reusing the most of the code base of your Web app while compiling the UI portion into native mobile components before the app is deployed. NativeScript is one of the frameworks that does it.

Most Web applications would need to provide login and user authentication/authorization. The chances are that you’ve been offered by some apps to login using their FaceBook or Twitter account. Usually such authorization is implemented using OAuth protocol. You can set up authorization using privately installed OAuth server that fits nicely with RESTful Web services.

This book sampler will give you a taste of multiple facets of the modern development of Web and mobile applications. Some of the books are already released while others are still in the works, but you can reading drafts via Manning’s MEAP program.

For this sampler I’ve suggested selected chapters from the following books:

1. RxJS in Action MEAP

2. Angular 2 Development with TypeScript

3. React in Action MEAP

4. NativeScript in Action MEAP

5. OAuth 2 in Action MEAP

This is not a complete list and there are other fine books being released by many book publishers. Here’s my message to you

“Read.Study.Write.Repeat.”

Happy reading!