Skip to content

Building, Testing, and Deploying with the CLI

Adarsh Kumar Maurya edited this page Dec 10, 2018 · 1 revision

Introduction

We've mentioned the Angular CLI a few times in this tutorial, but haven't really discussed what it is or what it can do. What seemed like wizardry is instead a full-featured tool for building, testing, and deploying our Angular applications. Welcome back to Angular: Getting Started, from Pluralsight. My name is Deborah Kurata, and in this chapter, we look closer at the Angular CLI. Let's peak behind the curtain and learn more about this amazing tool. In this chapter, we start with an overview and discover the purpose and basic features of the Angular CLI. We then build an application from scratch using this CLI, and examine the many configuration and startup files it creates. We dig into how it serves up our application, learn more about its code generation features, take a brief look at running tests, and prepare the resulting application for deployment. Let's get started.

Angular CLI Overview

The Angular CLI is a command line interface for Angular. Its primary purpose is to assist Angular developers with building an Angular application, generating Angular files, and executing, testing, and deploying Angular applications. Before you can use the CLI, you need to install it. Just open a terminal window or command prompt, and type npm install -g @angular/cli. This installs the CLI globally so you can use it from any folder. If you have not yet installed the CLI, do it now. Once you have it installed, we'll jump into a demo and try it out. I've already installed the CLI. Now, how can we find out what the CLI can do? One option is to use the ng help feature. We can see that it is listing every command. Let's try out the version command. Type ng for the Angular CLI, and the command. We'll use the v alias. And we see a nice text output, including our Angular CLI version. When you watch this tutorial, you may have a newer version. Use the help command any time you need assistance with the CLI commands or their flags. Now let's build a new application from scratch using the CLI.

ng new

Using the Angular CLI, we create a new Angular application using the new command. Let's try it out. Here in the terminal window, we'll type ng new and our new application name. Let's use a classic, hello-world. The CLI has the ability to provide prompts to ask for more information. The CLI may add or change prompts, so your experience may vary from what you see here. In this specific example, it's asking whether we want to add Angular routing to the application. To keep things simple for our demo, let's answer no. Next, it asks which stylesheet format we want. Use the arrow keys to select a desired format. We'll select CSS and press Enter to select. After we answer the last question, the CLI generates our application. Look at all the files that the CLI created. Notice that one of these files is package.json. Now the CLI is automatically installing the packages defined in that package.json file. This takes a bit of time, so I'll jump ahead. When the CLI new command is finished, we see a success message. Yay! The CLI creates a folder with the same name as the application name. Let's navigate down to the created hello-world folder. I'll then use the shortcut, code ., to open this folder in VS Code. Starting at the top, here is an e2e folder. This folder contains the start of an end-to-end test for the application. The node_chapters folder contains all of the libraries that were just installed by the CLI, as defined in the package.json file. The src folder contains the source code for our application. Below it is the app folder, where we'll add all of the chapters, components, services, and other files for our application. The assets folder is for any images or assets we want to include with the application. In our APM project, our welcome page logo is in this folder. The environments folder sets up our build environments. By default, it generates two, one for development and one for production. The CLI picks the appropriate environment file based on the flags we use. The CLI comes with the default favicon. Nice. Feel free to replace it with whatever is appropriate for your application. The index.html file is the first file downloaded when a user accesses our application. There isn't much here. You'd think that there would be at least a few script tags, but no. We'll see why a little later. In most cases you won't need to ever modify this file. The karma.config file sets up Karma, which is a JavaScript test runner. We'll use that for our unit tests. Main.ts is the file that bootstraps our application. This is another file you should never need to modify. The polyfills file aids in supporting both evergreen and classic browsers. Polyfills add code to allow functionality written for modern browsers to work in older browsers. By default, it is set up to support evergreen browsers, as stated here. If you need to target older browsers, there are comments in this file defining which additional libraries you need. Simply remove the comment marks from the desired libraries to include them. Here is a stylesheet for application-wide styles. As its name suggests, the tests file sets up for testing. The tsconfig files are for TypeScript configuration. There are two versions of this file, one for compiling our code files and the other for compiling our test specifications. Note that each of these extend our primary tsconfig file. That's it for the source folder. The editorconfig file provides some standard settings for your editor. The gitignore tells Git which files to ignore for checking into Git. Notice that our large node_chapters folder is included in this list. Let's skip the CLI configuration file for a moment and quickly cover the remaining files here. We walked through the package.json file in the First Things First chapter earlier in this tutorial. Here's a basic README and our primary tsconfig.json file. Lastly, there is a tslint configuration file. Tslint is a TypeScript linter which checks our code against a set of code style rules and notifies us if any of the rules aren't followed. This file defines those rules. Feel free to change these settings based on your team's selected code style preferences. Now let's go back to the CLI configuration file. This file is used to configure how the CLI generates code and works with our files. I'm not going to go through every option here, but want to point out a few key settings. The assets array allows us to provide a list of folders or files that are included with our application. This defines our application's selector prefix. Recall that in the APM application, we defined a prefix of PM. By default, the CLI creates a prefix of app. If you want to assign a unique prefix for your application, it is best to do that as part of the new command. Use ng new hello-world --prefix hw, for hello-world, or whatever prefix you prefer. Lastly, any global stylesheets are defined in this styles array. You can list any number of stylesheets as needed, but only include the global stylesheets here. So that's an overview of the basic files created by the CLI new command. Before moving on, let's look at a few key new command flags. Since we have VS Code open, we can now use its integrated terminal. I'll make it a little larger. Type ng new --help. Scrolling back to the top, we can see that it has many flags. The --skip-install is nice if you want to generate some code without waiting for it to install the node packages. You can install packages later using npm install. We've already discussed the --prefix flag. Feel free to create additional applications using the new command with any of these flags. Just note that you cannot generate a new Angular application within the folder of an existing Angular application, and so be sure to navigate out of the hello-world folder before using the new command. The next thing we want to do is run our application, so let's check out the serve command.

ng serve

Once we have a generated application, the first thing we may want to do is run it. We do that with the ng serve command. Let's give that a try. Here in the terminal window we'll type ng serve. The CLI launches a development server and listens on port 4200, as shown here. The application is then built, and we can see that it compiled successfully. The compiler is now in watch mode, so it watches for any changes and automatically recompiles for us. So, where is it? Where is our application? We can navigate to the defined port, 4200, and here is the application. It has a slick welcome page with links to the Tour of Heroes tutorial, the CLI Documentation, and the Angular team's blog. Feel free to check out those links. Previously in this tutorial, we used npm start to run our application, not ng serve. If we open the package.json file, we see that the npm start script is associated with the ng serve command. So using npm start basically executes ng serve. We can use Ctrl+C then y to stop execution, then type npm start. The process is the same. We can see that it executes ng serve. But we still have to manually bring up a browser and navigate to the appropriate port. We haven't had to do that for the other demos in this tutorial. What's up with that? Let's look back at the APM application in the package.json file that I included with the starter files for this application. I added -o to the start script. The -o is an alias for the --open flag, which opens the default browser. Mystery solved. Going back to the hello-world application, let's stop execution and restart with the -o flag. We type ng serve -o, which automatically opens our default browser and navigates to our application. But we can go into our package.json and update it here if we'd like. Before we move on, let's take a moment and look more closely at the output of the ng serve process. When we use the ng serve command, the CLI builds the application and outputs it as a set of bundled JavaScript and map files. Here we see the list of bundles. These files are generated in memory and are not available to find on disk. We'll generate actual files we can look at when we use the ng build command shortly. Here is the application in the browser. We'll open the Developer Tools and view the Sources tab. We see those same bundles here on the left. And notice our index.html file. The CLI injected the needed script tags for us to pull down all of these bundles. Another mystery solved. Peaking inside the main bundle, we see something that looks a bit like our code. Here is our app chapter, transpiled to JavaScript. Unless we specify otherwise, all of our application code will be compiled into this bundle. Since the CLI also generated the associated map files, we can see down here in the webpack node that we have our actual TypeScript code. This makes it much easier to debug our code, as we saw earlier in this tutorial. Now I'll close the browser and use Ctrl+C to stop the development server. Now let's look at some of the key flags available with the serve command. Type ng serve --help. There are lots of flags here. Many of these we'll use with the build command later. There are two I use regularly, the --port flag lets you specify an alternate port so you don't have to use 4200, and we've seen the effect of the --open flag. Now that we have an application and can run it, we'll want to add to it. Let's check out the generate command next.

ng generate

Our new little application is cool and all, but it doesn't do much. We need to add components and templates and services and chapters. We do that with the generate command. We've already seen this command in action, but it can do so much more. If we type ng g --help, this lists all of the different types of files we can generate with this command. We can create simple classes. We can create components with external template and stylesheet files, as we did with the product detail component earlier in this tutorial. We can generate our own custom directives, enum values, and route guards, as we did with our product detail guard. We can create interfaces and chapters. We can create pipes and services, all with only typing a few characters. Neat. Let's generate a component. Type ng g c, and our component name, let's say welcome. The output indicates that it created a stylesheet file, template HTML file, unit testing file, and TypeScript file for our component. By default, it created a welcome folder and added these files to it.

ng test

Testing our Angular code is always important, but often neglected due to the additional time and effort required to set up and execute the tests. The CLI makes it a bit easier by generating the testing spec and configuration files for us. We can run these tests using ng test and ng e2e. To run our unit tests, in the terminal window type ng test. This builds the application, launches the browser, and executes the Karma test runner. From here, we can see the results of our unit tests. Angular generated four tests for us and they've all passed, so we are all green. The test runner runs in watch mode, so we can modify our files and the tests will immediately re-run. I'll close the browser, and notice that it tried to bring it up again. I first need to terminate the test runner with Ctrl+C, then I'll clear the screen with cls. We can use the e2e command to run our end-to-end tests using Protractor. Let's try that out. Ng e2e. Notice that it pops up the browser, executes our application, and closes the browser again. We can see here that it successfully executed one spec. Testing is a big topic that is beyond the scope of this tutorial. See the Pluralsight library for more information about testing. Now that we have our application built and tested, we are ready to deploy.

ng build

An application is not very useful unless you can deploy it to your users. The build command helps you prepare your application for deployment. Let's take a look. Here in the terminal window, we'll type ng build. The output is similar to the ng serve command, but now we see a dist folder here in our project. If we open the folder, we see our actual bundles. We can look again at the main bundle .js file and find our code. And here is the resulting index.html file with the script tags to pull in each bundle. We can then deploy these files to a server somewhere. But wait, there's more. When we deploy to production there are a few more things that we want to achieve. We want our bundles to be as small as possible. This means that we want to minify or uglify the code and perform something called tree shaking. Tree shaking shakes up our code to drop out any dead branches, which basically means that it removes any unused pieces. We also want to precompile our templates, so instead of downloading the Angular compiler as part of the vendor bundles, and running the compiler in the browser, we can make the bundles smaller and execute faster if we precompile before we deploy. This makes use of the AOT, or ahead-of-time compiler. The CLI will do all of these things for us if we simply add the --prod flag. Let's try that out. Type ng build --prod. Now if we look at the files in the dist folder, we notice that they have a hash as part of the file name. This is a cache-busting technique. Every time we update something in our code, it needs to be redeployed to the server. We expect the new version of the files to be downloaded by the browser when a user accesses our application, but for performance reasons, the browser may have cached those files. By changing the file names using a hash, the browser will download the latest version because the file names won't match its cached versions. Notice also that there are no map files here. By default, the --prod flag does not generate map files, but there is a flag for that if you need them. Peeking into the main bundle, all the code is on one line, and look at those variable names. It's been minified. Glad we don't have to debug using that code. Let's look at some of the key flags available with the build command. Type ng build --help. We'll scroll up a bit. There are quite a few flags here to help you tune exactly what you want the build command to do. One of the other key flags here is the --base-href. Recall that we set the base element in our index.html file to specify the route path for our Angular routing, but when we deploy to production, we may not want to deploy to the route path of our server. We can use the --base-href flag to set the appropriate base URL for the deployed application. Wow, the CLI is powerful. Now let's finish up this chapter with some checklists we can use as we leverage the Angular CLI.

Checklists and Summary

Here are the key CLI commands for reference. Use ng help or ng, a command name, --help to view the CLI documentation. The remaining commands here help you create, execute, build, test, and deploy your Angular application. You may find yourself using ng generate a lot. Refer to this checklist as you generate the code files for your application. In this chapter, we discovered the purpose and basic features of the CLI. We built an application from scratch and examined its many configuration and startup files. We dug into how it serves up our application, learned about its code generation features, looked at running tests, and prepared the resulting application for deployment. Now that we've peeked behind the curtain, you know the secrets of the CLI. There is no wizardry here. There are more commands and many more flags than what we discussed in this chapter. To learn more about the Angular CLI, check out John Papa's tutorial, aptly entitled Angular CLI in the Pluralsight library. It covers many more of its amazing features. Only one chapter left.