Create an Ionic 4 PWA with Capacitor
Tags: ionic, javascript, pwa, angular
Published: 2019-03-22 17:01:55

---
title: Create an Ionic 4 PWA with Capacitor
published: true
description: In this tutorial, we’ll learn to build a Progressive Web Application (PWA) with Ionic 4 and Capacitor and take advantage of the many benefits of PWAs.
tags: Ionic, JavaScript, PWA, Angular
canonical_url: https://blog.jscrambler.com/create-an-ionic-4-pwa-with-capacitor/
cover_image: https://blog.jscrambler.com/content/images/2019/03/jscrambler-blog-create-ionic-4-pwa-capacitor.jpg
---

In this tutorial, we’ll learn to build a **Progressive Web Application (PWA)** with Ionic 4 and Capacitor.

A PWA is a web application similar to traditional web apps but provides extra features for users that were only available in native mobile apps like instant loading, add-to-home screen, splash screens, access to device capabilities, push notifications and offline support.

The term “Progressive” in Progressive Web Apps refers to how these apps provide web experiences which are **reliable** - by loading instantly regardless of network conditions - **fast** - by responding immediately and smoothly to every user interaction - and **engaging** - by providing an immersive and natural user experience.

To achieve these demanding user experience primers, a PWA makes use of Service Workers for supporting features like instant loading and offline support so it needs to be securely served via HTTPS, as Service Workers only work under HTTPS connections. PWAs achieve support for all modern and old browsers, which is an important aspect of this kind of apps. Since they use modern features that might not be available in all browsers, PWAs make use of progressive enhancement which is using the feature when it’s available and use a fallback for browsers which don’t support it.

The application we'll be building is a simple JavaScript Jargon app that's based on the Simplified JavaScript Jargon available on [GitHub](https://github.com/HugoGiraudel/SJSJ). We'll export the entries as JSON data and we'll consume them from our PWA. We already created a statically generated JSON API available [here](https://media.jscrambler.com/blog/data.json).

You can find the source code of this app in this [GitHub repository](https://github.com/techiediaries/ionic-capacitor-pwa).

> **Note**: If you would like to consume an API from your server, make sure you have [CORS](https://blog.jscrambler.com/understanding-cors-cross-origin-resource-sharing/) enabled in your web server. Otherwise, the web browser will block your requests due to the **Same Origin Policy** available on modern browsers. 

Now, let’s get started!

## Prerequisites

- You will need to have a development environment with Node.js and npm installed. You can install both of them by going to the [official website](https://www.nodejs.org) and grab the binaries for your system.
- Familiarity with TypeScript since we’ll be using [Ionic 4](https://blog.jscrambler.com/introduction-to-ionic-4/) with Angular.

## Generating a New Ionic 4 Project

Let’s start by installing Ionic CLI globally on your system from npm using the following command:

```bash
npm install -g ionic
```
Using the CLI, you can generate a new project using the following command:

```bash
ionic start
```

The CLI will prompt you for information about your project, such as the name (enter **jsjargonpwa**) and starter template (choose **sidemenu**). This will set up your project.

When prompted for **Install the free Ionic Appflow SDK and connect your app? (Y/n)** just type `n`.

You can now navigate to your project’s folder and serve your application locally using:

```bash
cd ./jsjargonpwa
ionic serve
```

Your application will be available from the `http://localhost:8100` address.

We’ll be working on the home page, so you can remove the list page. First, delete the list folder containing the files; next, open the `src/app/app.component.ts` file and delete the entry for the list page from the `appPages` array:

```javascript
     public appPages = [
       {
         title: 'Home',
         url: '/home',
         icon: 'home'
       }
     ];
```

Next, open the `src/app/app-routing.module.ts` file and delete the route for the list page:

```javascript
   const routes: Routes = [
     {
       path: '',
       redirectTo: 'home',
       pathMatch: 'full'
     },
     {
       path: 'home',
       loadChildren: './home/home.module#HomePageModule'
     }
   ];
```

## Getting JSON Data

We’ll use `HttpClient` from Angular to send a GET request to our server to fetch the JSON entries. Before that, we need to import it in our project.

First, open the `src/app/home/home.module.ts` file and import `HttpClientModule`:

```javascript
   // [...]
   import { HttpClientModule } from '@angular/common/http';
  
   @NgModule({
     imports: [
       /* [...] */
       HttpClientModule
     ],
     declarations: [HomePage]
   })
   export class HomePageModule {}
```

Next, open the `src/app/home/home.page.ts` file and update it accordingly:

```javascript
   import { Component } from '@angular/core';
   import { HttpClient } from '@angular/common/http';
   @Component({
     selector: 'app-home',
     templateUrl: 'home.page.html',
     styleUrls: ['home.page.scss'],
   })
   export class HomePage {
     API_URL = "https://media.jscrambler.com/blog/data.json";
     entries: Array<any>;
     constructor(private httpClient: HttpClient){
     }
     ionViewDidEnter(){
       this.getData();
     }
     getData(){
       this.httpClient.get(this.API_URL).subscribe((entries: any[])=>{
         this.entries = entries;
       })
     }
  
   }
```

We declare two variables: `API_URL` — which holds the address of the JSON file that we need to fetch — and `entries`, an array that will hold the entries.

Now, let’s inject `HttpClient` as `httpClient` via the component’s constructor.

Next, we add a `getData()` method that calls the `get()` method of `HttpClient` and subscribe to the returned Observable. We then assign the fetched data to the `entries` variable. 

Finally, we add the `ionViewDidEnter()` event that gets called when the Ionic page is loaded and we call the `getData()` method to fetch the entries once the page is loaded.

Next, open the `src/app/home/home.page.html` file and update it as follows:

```html
   <ion-header>
     <ion-toolbar>
       <ion-buttons slot="start">
         <ion-menu-button></ion-menu-button>
       </ion-buttons>
       <ion-title>
         JSJargon
       </ion-title>
     </ion-toolbar>
   </ion-header>
   <ion-content>
       <ion-list lines="none">
         <ion-item *ngFor = "let entry of entries">
           <ion-card>
             <ion-card-header>
               <ion-card-title>{{ entry.name }}</ion-card-title>
             </ion-card-header>
             <ion-card-content>
               <p>{{ entry.description }}</p>
             </ion-card-content>
           </ion-card>
         </ion-item>
       </ion-list>
   </ion-content>
```

We simply loop through the `entries` variable and display the name and description of each entry using an Ionic card.

This is a screenshot of the result:

<center>![App Screenshot 1](https://blog.jscrambler.com/content/images/2019/03/jscrambler-blog-create-ionic-4-pwa-capacitor-app-screenshot-1.png)</center>

## Adding Capacitor

[Capacitor](https://capacitor.ionicframework.com/) is an open source native container (similar to Cordova) built by the Ionic team that you can use to build web/mobile apps that run on iOS, Android, Electron (Desktop), and as Progressive Web Apps with the same code base. It allows you to access the full native SDK on each platform, and easily deploy to App Stores or create a PWA version of your application.

Capacitor can be used with Ionic or any preferred frontend framework and can be extended with plugins. It has a rich set of [official plugins](https://capacitor.ionicframework.com/docs/apis/) and you can also use it with [Cordova plugins](https://cordova.apache.org/plugins/).

<a href="https://blog.jscrambler.com/protecting-hybrid-mobile-apps-with-ionic-and-jscrambler/?utm_source=dev.to&utm_medium=referral" target="_blank"><img alt="Protect your Code with Jscrambler" src="https://media.jscrambler.com/blog/V1-Ionic.jpg"></a>

## Installing Capacitor

Let’s start by installing Capacitor in your project:

```bash
npm install --save @capacitor/cli @capacitor/core
```

Next, you need to initialize Capacitor with `npx cap init \[appName\] [appId]`:

```bash
npx cap init jsjargon com.techiediaries.jsjargon
```

## Using the Clipboard Plugin

Now, let’s use the Clipboard Capacitor plugin in our project to see how Capacitor works by example.

Open the `src/app/home/home.page.ts` file and add:

```javascript
import { Plugins } from '@capacitor/core';
const { Clipboard } = Plugins;
```

Next, add the `copy()` method which will be used to copy a JS term to the clipboard:

```javascript
     async copy(name: string, text: string){
       Clipboard.write({
         string:  name + ' is ' + text
       });
     }
```

Finally, open the `src/app/home/home.page.html` file and add a button to the Ionic card for each entry:

```html
           <ion-card>
             <ion-card-header>
               <ion-card-title>{{ entry.name }}</ion-card-title>
             </ion-card-header>
             <ion-card-content>
               <p>{{ entry.description }}</p>
             </ion-card-content>
               <ion-button (click)="copy(entry.name, entry.description)">
                 Copy
               </ion-button>
           </ion-card>
```

This is a screenshot of the result:

<center>![App Screenshot 2](https://blog.jscrambler.com/content/images/2019/03/jscrambler-blog-create-ionic-4-pwa-capacitor-app-screenshot-2.png)</center>

## Adding a Web Manifest and A Service Worker

A web manifest and service worker are essential requirements for a PWA. You can add both of them using the `@angular/pwa` package. In your terminal, run:

```bash
cd jsjargonpwa
ng add @angular/pwa
```

This is a screenshot of what `@angular/pwa` has added and updated in your project:

<center>![CLI Angular Added](https://blog.jscrambler.com/content/images/2019/03/jscrambler-blog-create-ionic-4-pwa-capacitor-app-angular.png)</center>

For example, a `src/manifest.webmanifest` file is created and referenced in the `index.html` file:

```html
   <link rel="manifest" href="manifest.webmanifest">
```

Also, different default icons were added in the `src/assets/icons` folder. In production, you will need to change these icons with your own.

In the `src/app/app.module.ts` file, a service worker is registered using the following line:

```javascript
   ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
```

This is only enabled for production so you will need to build your application for production to register the service worker.

Next, we need to build our application for production using the following command:

```bash
ionic build --prod
```

Finally, we need to use a hosting service like [Netlify](https://netlify.com) to securely host the application over HTTPS (required by a PWA).  Here is the [link](https://objective-ride-b228de.netlify.com/) to our hosted PWA.


## Conclusion

In this tutorial, we’ve seen how to create a PWA with Ionic 4, Angular and Capacitor.

We have seen an example of sending GET requests using `HttpClient` and how to access the device clipboard using the Clipboard Capacitor plugin. We hope that this tutorial has been useful in helping you with your own projects.

**If you're building Ionic applications with sensitive logic, be sure to protect them against code theft and reverse-engineering by following <a href="https://blog.jscrambler.com/protecting-hybrid-mobile-apps-with-ionic-and-jscrambler/?utm_source=dev.to&utm_medium=referral" target="_blank">our guide</a>**.

This article was originally published on the [Jscrambler Blog](https://blog.jscrambler.com/create-an-ionic-4-pwa-with-capacitor/?utm_source=dev.to&utm_medium=referral) by Ahmed Bouchefra.