Appendix C. Using the npm package manager

This appendix is an overview of the tools we use to install Angular and its dependencies using the npm package manager.

For most of this book, we use Node.js for installing software. Node.js (or simply Node) isn’t just a framework or a library: it’s a JavaScript runtime environment as well. We use the Node runtime for running various utilities like npm or launching JavaScript code without a browser. We also use npm scripts to automate building, testing, and deploying Angular apps.

To get started, download and install the current version of Node.js from https://nodejs.org. After installation is complete, open your terminal or command window and enter the following command:

node --version

This command should print the version of Node installed, for example, 10.3.0. Node comes with the package manager npm, which we use to install Angular and other packages from the npm registry located at www.npmjs.com. This repository hosts Angular as well as more than 400,000 other JavaScript packages.

The Node.js framework

Node.js is also a framework that can be used to develop JavaScript programs that run outside the browser. You can develop the server-side layer of a web application in JavaScript or Typescript. We write a web server using Node in chapter 12 by using Node.js and Express frameworks. Google developed a high-performance V8 JavaScript engine for the Chrome browser, and it can also be used to run code written using the Node.js API. The Node.js framework includes an API to work with the filesystem, access databases, listen to HTTP requests, and more.

To install a JavaScript library, run the command npm install, or npm i for short. Say you want to install the TypeScript compiler locally. Open the Terminal in any directory and run the following command:

npm i typescript

After this command completes, you’ll see a new subdirectory named node_modules, where the TypeScript compiler has been installed. npm always installs packages in the node_modules directory. If such a directory doesn’t exist, npm will create it.

If you want to install a package globally, add the -g option:

npm i typescript -g

This time the TypeScript compiler will be installed not in the current directory, but globally in the lib/node_modules subdirectory of your Node.js installation.

If you want to install a specific version of the package, add the version number to the package name after the @ sign. For example, to install Typescript 2.9.0 globally, use the following command:

npm i [email protected] -g

All available options of the npm install command are described at https://docs.npmjs.com/cli/install.

In some cases, you may want to have the same package installed both locally and globally. As a example, you may have the TypeScript compiler 2.7 installed locally, and TypeScript 2.9 installed globally. To run the global version of this compiler, you enter the tsc command in your terminal or command window, and to run the locally installed compiler, you could use the following command from your project directory:

node_modules/.bin/tsc

A typical Node-based project may have multiple dependencies, and we don’t want to keep running separate npm i commands to install each package. Creating a package .json file is a better way to specify all project dependencies.

C.1. Specifying project dependencies in package.json

To start a new Node-based project, create a new directory (for example, my-node-project), open your terminal or command window, and change the current working directory to the newly created one. Then run the npm init -y command, which will create the initial version of the package.json configuration file. Normally, npm init asks several questions while creating the file, but the -y flag makes it accept the default values for all options. The following example shows this command running in the empty my-node-project directory:

$ npm init -y
Wrote to /Users/username/my-node-project/package.json:

{
  "name": "my-node-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Most of the generated configuration is needed either for publishing the project into the npm registry or while installing the package as a dependency for another project. We’ll use npm only for managing project dependencies and automating development and build processes.

Because we’re not going to publish it into the npm registry, remove all the properties except name, description, and scripts. Also, add a "private": true property, because it’s not created by default. That will prevent the package from being accidentally published to the npm registry. The package.json file should look like this:

{
  "name": "my-node-project",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  }
}

The scripts configuration allows you to specify command aliases that you can run in your command window. By default, npm init creates the test alias, which can be run like this: npm test. The generated script command include double ampersands, &&, which are used as a separator between commands. When you run npm test, it runs two commands: echo "Error: no test specified" and exit -1. npm scripts support about a dozen command names like test, start, and others. A list of these commands is at https://docs.npmjs.com/misc/scripts.

You can create your own command aliases with any names:

"scripts": {
    "deploy": "copyfiles -f dist/** ../server/build/public",
  }

Because deploy is a custom alias name, you need to run this command by adding the keyword run:

npm run deploy

In section 12.3.6 in chapter 12, we discuss how to write npm scripts for building and deploying an app on the web server.

If you generate package.json using the npm init command, it’ll be missing two important sections: dependencies and devDependencies. Let’s see how dependencies of an Angular project are specified. Figure C.1 shows a fragment from a package.json file of a typical Angular project.

Figure C.1. Angular dependencies in package.json

It looks intimidating, but the good news is that you don’t need to remember all these packages and their versions, because you’ll be generating projects with Angular CLI, which will create the file package.json with the proper content.

The dependencies section lists all the packages required for your application to run. As you can see, the Angular framework comes in several packages with names starting with @angular. You may not need to install all of them. If your app doesn’t use forms, for example, there’s no need to include @angular/forms in your package.json.

The devDependencies section lists all the packages required to be installed on a developer’s computer. It includes several packages, and none of them is needed on the production server. There’s no need to have testing frameworks or a TypeScript compiler on the production machine, right?

To install a single package with npm, list the name of this package. For example, to add the Lodash library to your node_modules directory, run the following command:

npm i lodash

To add the package to node_modules and add the corresponding dependency to the dependencies section of your package.json file, you can explicitly specify the --save-prod option:

npm i lodash --save-prod

You can also use the abbreviation -P for --save-prod. If no options are specified, the npm i lodash command updates the dependencies section of the package.json file.

To add the package to node_modules and add the corresponding dependency to the devDependencies section of your package.json file, use the --save-dev option:

npm i protractor --save-dev

You can also use the abbreviation -D for --save-dev.

Sometimes the GitHub version of a package has an important bug fix that hasn’t been released yet on npmjs.org. If you want install such a package from GitHub, you need to replace the version number in package.json dependencies with its location on GitHub. Changing the dependency to include the name of the GitHub organization and repository should allow you to install the latest builds from GitHub versions of this library. For example:

"@angular/flex-layout": "angular/flex-layout-builds"

The preceding configuration will work, assuming that the master branch of the Flex Layout library has no code issues preventing npm from installing it.

C.2. Semantic versioning

Numbering of Angular releases uses a set of rules known as semantic versioning. The version of a package consists of three digits—for example, 6.1.2. The first digit denotes a major release that includes new features and potentially breaking changes in the API. The second digit represents a minor release, which introduces new backward-compatible APIs but has no breaking changes. The third digit represents backward-compatible patches with bug fixes.

Take another look at figure C.1 in the previous section. Every package has a three-digit version, and many of them have additional symbols: ^ or ~. If the specified version has just the three digits, that means you instruct npm to install exactly that version. For example, the following line in package.json tells npm to install Angular CLI version 6.0.5, ignoring the newer versions even if they’re available:

"@angular/cli": "6.0.5"

Many packages in that package.json file have the hat sign ^ in front of the version. For example:

"@angular/core": "^6.0.0"

This means you’ll allow npm to install the latest minor release of version 6 if available. If the latest version of the Angular Core package is 6.2.1, it will be installed.

The tilde ~ means you want to install the latest patch for the given major and minor version:

"jasmine-core": "~2.99.1"

There are many other symbols you can use with version numbers with npm—see http://mng.bz/YnyW for details.

C.3. Yarn as an alternative to npm

Yarn (see https://yarnpkg.com) is another package manager that can be used as an alternative to npm. Prior to version 5, npm was slow, which was one reason we started using the faster Yarn.

Now npm is fast too, but Yarn has an additional benefit: it creates the file yarn.lock that keeps track of exact versions of packages that were installed in your project. Let’s say your package.json file has a "@angular/core": "^6.0.0" dependency, and your project has no yarn.lock file. If version 6.1.0 is available, it’ll be installed, and yarn.lock is created with a record about the version 6.1.0. If you run yarn install in a month, and if yarn.lock exists in your project, Yarn will use it and install version 6.1.0, even if version 6.2.0 is available.

The following fragment from yarn.lock shows that although the dependency in package.json for the @angular/core package was set as ^6.0.0, version 6.0.2 was installed:

"@angular/core@^6.0.0":
  version "6.0.2"
  resolved "https://registry.yarnpkg.com/@angular/core/-/core-
     6.0.2.tgz#d183..."
  dependencies:
    tslib "^1.9.0"

In a team setup, you should check the yarn.lock file into the version control repository so every member of your team has the same versions of packages.

npm also creates the package-lock.json file, but npm isn’t designed to install exact package version(s) listed in this file if you run npm install (see https://github.com/npm/npm/issues/17979). The good news is that starting from version 5.7, npm supports the npm ci command, which ignores the versions listed in package.json, but installs the versions listed in the package-lock.json file.

If at some point you decide to upgrade packages, overriding the versions stored in yarn.lock, run the yarn upgrade-interactive command, as shown in figure C.2.

Figure C.2. Upgrading package versions with Yarn

Yarn works with your project’s package.json file, so there’s no need for any additional configuration. You can read more about using Yarn at https://yarnpkg.com/en/docs.

Tip

You can ask Angular CLI to use Yarn instead of npm while installing dependencies of the newly generated project. Starting with Angular CLI 6, you can do this by using the following command:

ng config --global cli.packageManager yarn

If you use older versions of Angular CLI, use the following command:

ng set --global packageManager=yarn
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.38.117