In this chapter, I prepare the SportsStore application for deployment by adding progressive features that will allow it to work while offline and show you how to prepare and deploy the application into a Docker container, which can be used on most hosting platforms.
Preparing the Example Application
No preparation is required for this chapter, which continues using the SportsStore project from Chapter 9.
Tip
You can download the example project for this chapter—and for all the other chapters in this book—from https://github.com/Apress/pro-angular-6 .
Adding Progressive Features
A progressive web application (PWA) is one that behaves more like a native application, which means it can continue working when there is no network connectivity, its code and content are cached so it can start immediately, and it can use features such as notifications. Progressive web application features are not specific to Angular, but in the sections that follow, I add progressive features to the SportsStore application to show you how it is done.
Tip
The process for developing and testing a PWA can be laborious because it can be done only when the application is built for production, which means that the automatic build tools cannot be used.
Installing the PWA Package
The Angular team provides an NPM package that can be used to bring PWA features to Angular projects. Run the command shown in Listing 10-1 in the SportsStore folder to download and install the PWA package.
Tip
Notice that this command is ng add, rather than the npm install command that I use elsewhere for adding packages. The ng add command is used specifically to install packages, such as @angular/pwa, that have been designed to enhance or reconfigure an Angular project.
Installing a Package
Caching the Data URLs
Caching the Data URLs in the ngsw-config.json File in the SportsStore Folder
The PWA’s code and content required to run the application are cached and updated when new versions are available, ensuring that updates are applied consistently when they are available, using the configuration in the assetGroups section of the configuration file. In addition, I have added an entry so that the files required by the Font Awesome package are cached.
The application’s data is cached using the dataGroups section of the configuration file, which allows data to be managed using its own cache settings. In this listing, I configured the cache so that it will contain data from 100 requests and that data will be valid for 5 days. The final configuration section is navigationUrls, which specifies the range of URLs that will be directed to the index.html file. In this example, I used a wildcard to match all URLs.
Note
I am just touching the surface of the cache features that you can use in a PWA. There are lots of choices available, including the ability to try to connect to the network and then fall back to cached data if there is no connection. See https://angular.io/guide/service-worker-intro for details.
Responding to Connectivity Changes
The Contents of the connection.service.ts File in the src/app/model Folder
Adding a Service in the model.module.ts File in the src/app/model Folder
Receiving a Service in the cartDetail.component.ts File in the src/app/store Folder
Reflecting Connectivity in the cartDetail.component.html File in the src/app/store Folder
Preparing the Application for Deployment
In the sections that follow, I prepare the SportsStore application so that it can be deployed.
Creating the Data File
The Contents of the serverdata.json File in the SportsStore Folder
Creating the Server
When the application is deployed, I am going to use a single HTTP port to handle the requests for the application and its data, rather than the two ports that I have been using in development. Using separate ports is simpler in development because it means that I can use the Angular development HTTP server without having to integrate the RESTful web service. Angular doesn’t provide an HTTP server for deployment, and since I have to provide one, I am going to configure it so that it will handle both types of request and include support for HTTP and HTTPS connections, as explained in the sidebar.
USING SECURE CONNECTIONS FOR PROGRESSIVE WEB APPLICATIONS
When you add progressive features to an application, you must deploy it so that it can be accessed over secure HTTP connections. If you do not, the progressive features will not work because the underlying technology—called service workers—won’t be allowed by the browser over regular HTTP connections.
You can test progressive features using localhost, as I demonstrate shortly, but an SSL/TLS certificate is required when you deploy the application. If you do not have a certificate, then a good place to start is https://letsencrypt.org , where you can get one for free, although you should note that you also need to own the domain or hostname that you intend to deploy to generate a certificate. For the purposes of this book, I deployed the SportsStore application with its progressive features to sportsstore.adam-freeman.com, which is a domain that I use for development testing and receiving emails. This is not a domain that provides public HTTP services, and you won’t be able to access the SportsStore application through this domain.
Installing Additional Packages
The Contents of the server.js File in the SportsStore Folder
The server is configured to read the details of the SSL/TLS certificate from files in the ssl folder, which is where you should place the files for your certificate. If you do not have a certificate, then you can disable HTTPS by setting the enableHttps value to false. You will still be able to test the application using the local server, but you won’t be able to use the progressive features in deployment.
Changing the Web Service URL in the Repository Class
Changing the URL in the rest.datasource.ts File in the src/app/model Folder
Building and Testing the Application
Building the Application for Production
This command builds an optimized version of the application without the additions that support the development tools. The output from the build process is placed in the dist/SportsStore folder. In addition to the JavaScript files, there is an index.html file that has been copied from the SportsStore/src folder and modified to use the newly built files.
Note
Angular provides support for server-side rendering, where the application is run in the server, rather than the browser. This is a technique that can improve the perception of the application’s startup time and can improve indexing by search engines. This is a feature that should be used with caution because it has serious limitations and can undermine the user experience. For these reasons, I have not covered server-side rendering in this book. You can learn more about this feature at https://angular.io/guide/universal .
Starting the Production HTTP Server
Testing the Progressive Features
Containerizing the SportsStore Application
To complete this chapter, I am going to create a container for the SportsStore application so that it can be deployed into production. At the time of writing, Docker is the most popular way to create containers, which is a pared-down version of Linux with just enough functionality to run the application. Most cloud platforms or hosting engines have support for Docker, and its tools run on the most popular operating systems.
Installing Docker
The first step is to download and install the Docker tools on your development machine, which is available from www.docker.com/products/docker . There are versions for macOS, Windows, and Linux, and there are some specialized versions to work with the Amazon and Microsoft cloud platforms. The free Community edition is sufficient for this chapter.
Caution
One drawback of using Docker is that the company that produces the software has gained a reputation for making breaking changes. This may mean that the example that follows may not work as intended with later versions. If you have problems, check the repository for this book for updates ( https://github.com/Apress/pro-angular-6 ) or contact me at [email protected].
Preparing the Application
The Contents of the deploy-package.json File in the SportsStore Folder
The dependencies section omits Angular and all of the other runtime packages that were added to the package.json file when the project was created because the build process incorporates all of the JavaScript code required by the application into the files in the dist/SportsStore folder. The devDependencies section includes the tools required by the production HTTP/HTTPS server.
The scripts section of the deploy-package.json file is set up so that the npm start command will start the production server, which will provide access to the application and its data.
Creating the Docker Container
The Contents of the Dockerfile File in the SportsStore Folder
The contents of the Dockerfile use a base image that has been configured with Node.js and copies the files required to run the application, including the bundle file containing the application and the package.json file that will be used to install the packages required to run the application in deployment.
The Contents of the .dockerignore File in the SportsStore Folder
Building the Docker Image
An image is a template for containers. As Docker processes the instructions in the Docker file, the NPM packages will be downloaded and installed, and the configuration and code files will be copied into the image.
Running the Application
Once the image has been created, create and start a new container using the command shown in Listing 10-17.
Tip
Make sure you stop the test server you started in Listing 10-12 before starting the Docker container since both use the same ports to listen for requests.
Starting the Docker Container
Listing the Containers
Stopping the Container
The application is ready to deploy to any platform that supports Docker, although the progressive features will work only if you have configured an SSL/TLS certificate for the domain to which the application is deployed.
Summary
This chapter completes the SportsStore application, showing how an Angular application can be prepared for deployment and how easy it is to put an Angular application into a container such as Docker. That’s the end of this part of the book. In Part 2, I begin the process of digging into the details and show you how the features I used to create the SportsStore application work in depth.