CHANGE LOG
- UPDATE 2019–05–04: Replaced firebase screenshot with English version
- UPDATE 2019–05–16: Fixed issue about 7. cURL

- UPDATE 2019–06–11: Changed how to “Add to Home Screen” on desktop chrome

What’s PWA?

There’re the following functions about PWA (Progressive Web App).

  • Service Workers
  • Add to Home Screen
  • Push Notifications

By using PWA, you can provide UX that is similar to Native Application to users even through you develop it as Web Application.

I’m going to try these functions with Vue.js.


PWA w/ Vue CLI 3

Demo

https://vue-pwa-tutorial.firebaseapp.com

Source Code

https://github.com/n11sh1/vue-pwa-tutorial

Tutorial

1. Install Vue CLI 3

Ref. Installation | Vue CLI 3
$ npm install -g @vue/cli

2. Create a new project

$ vue create vue-pwa-tutorial

3. Select manually

Vue CLI v3.3.0?
Please pick a preset:
   default (babel, eslint) 
❯ Manually select features

4. Select PWA

Typescript, Router, Vuex as you like.

Vue CLI v3.3.0
? Please pick a preset: Manually select features
? Check the features needed for your project: 
❯◉ Babel
 ◉ TypeScript
 ◉ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

5. After that appropriately

Vue CLI v3.3.0
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, PWA, Router, Vuex, Linter
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript for auto-detected polyfills? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: TSLint
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects
? Yes? Save preset as:

6. Initialize

Vue CLI v3.3.0
✨  Creating project in /Users/zyyx-kubo/WVVUProjects/chatty/vue-pwa-tutorial.
🗃  Initializing git repository...
⚙  Installing CLI plugins. This might take a while...

7. Run web server

$ cd vue-pwa-tutorial/
$ npm run serve

8. Access to localhost

Laptop
Mobile

PWA — Service Workers

If you start with npm run serve , Service Workers will not work as follows.

Developer Tool > Application > Service Workers

To check the behavior Service Workers you need to build with npm run build .
If you publish the ./dist directory using Web Server for Chrome , you can check that Service Workers is working as follows. (Usually start with npm run servewhen you don’t use Service Workers)

$ npm run build
 DONE  Build complete. The dist directory is ready to be deployed.
Developer Tool > Application > Service Workers
Developer Tool > Application > Cache Storage

Static contents(*.html, *.css, *.js, *.txt) are cached.

Checked Developer Tool > Application > Service Workers > Update on reload, and Cache is cleared every time on browser reload. Otherwise delete the target file from Cache Storage.


PWA — Add to Home Screen

Web App Manifest

In order to display the “Add to Home Screen” dialog, JSON formatted Web App Manifest file is required.

If you selected PWA with Vue CLI, it will be create by default, so use that as it is.

{
    "name": "vue-pwa-tutorial",
    "short_name": "vue-pwa-tutorial",
    "icons": [
    	{
        	"src": "./img/icons/android-chrome-192x192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
        	"src": "./img/icons/android-chrome-512x512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ],
    "start_url": "./index.html",
    "display": "standalone",
    "background_color": "#000000",
    "theme_color": "#4DBA87"
}

Local Environment

chrome://apps/

Deploy to the server because you can’t check it by mobile phone.

Build Demonstration Environment by Firebase Hosting

As a reason to use Firebase, I will try Push Notifications next time. so it’s a foundation for that.

Ref. Deployment Firebase | Vue CLI 3
  1. Create a new project on Firebase

At first sign in to Firebase console with Google account, and create a new project.

Firebase console

2. Deploy

Installing Firebase CLI because deployment runs with command line.

$ npm install -g firebase-tools

$ firebase login

Initialization by project root.

$ firebase init hosting

? Select a default Firebase project for this directory: (Use arrow keys)
  [don't setup a default project]
❯ vue-pwa-tutorial (vue-pwa-tutorial)
  [create a new project]
  
? What do you want to use as your public directory? (public) dist

? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) y

? File dist/index.html already exists. Overwrite? (y/N) y

Deployment

$ firebase deploy --only hosting

Icon is now added to home screen as well as Native Application. (Also the trouble of installing from AppStore was reduced)

Since static contents are cached, it works quickly. (Although API seems be able to cache too, but this time it is omitted)


PWA — Push Notifications

I use Firebase Cloud Messaging(FCM) for Push Notifications.

Ref. Set up a JavaScript Firebase Cloud Messaging client app | Firebase
Ref. Receive messages in a JavaScript client | Firebase
Ref. Firebase Cloud Messaging Quickstart | GitHub
  1. Configure Web Credentials with FCM
Generate a new key pair (Settings > Could Messaging)

2. Add the gcm_sender_id in Web App Manifest

{
    ...,
    "gcm_sender_id": "103953800507"
}

3. Install Firebase SDK

$ npm install --save firebase

4. Get Firebase Configuration

Step 1
Step 2
Step 3
Step 4
Step 5
Finish (Settings > General)

5. Request Permission of Notifications and Get Token

import * as firebase from "firebase";

var config = {
    apiKey: "xxxxxxxxxxxx",
    authDomain: "xxx.firebaseapp.com",
    databaseURL: "https://xxx.firebaseio.com",
    projectId: "xxx",
    storageBucket: "xxx.appspot.com",
    messagingSenderId: "xxxxxxxxxxxx"
}; // 4. Get Firebase Configuration
firebase.initializeApp(config);

const messaging = firebase.messaging();messaging.usePublicVapidKey("xxxxxxx"); // 1. Generate a new key pair

// Request Permission of Notifications
messaging.requestPermission().then(() => {
    console.log('Notification permission granted.');
    
    // Get Token
    messaging.getToken().then((token) => {
        console.log(token)
    })
}).catch((err) => {
    console.log('Unable to get permission to notify.', err);
});

6. Add Service Worker for FCM

In order to receive the onMessage event, your app must define the Firebase messaging service worker in firebase-messaging-sw.js. Alternatively, you can specify an existing service worker with useServiceWorker.

// [START initialize_firebase_in_sw]
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the messagingSenderId.
firebase.initializeApp({
    'messagingSenderId': 'xxxxxxxxx' // 4. Get Firebase Configuration
});

// Retrieve an instance of Firebase Messaging so that it can handle background messages.
const messaging = firebase.messaging();
// [END initialize_firebase_in_sw]

Because Push Notification needs that Service Worker is running, npm run build and access to localhost with Web Server for Chrome.

Request Permission
Get Token

7. Receive Test Message via cURL

Cloud Messaging > Server key
$ curl -X POST -H "Authorization: key=${The above server key}" -H "Content-Type: application/json" -d '{  "to": "${5’s token}",  "notification": {    "title": "FCM Message",    "body": "This is an FCM Message",    "icon": "./img/icons/android-chrome-192x192.png"  }}' https://fcm.googleapis.com/fcm/send
Success
Not receive a message if target page is active
Permission dialog
Success
A notification dot is also attached to icon

Summary

By using PWA you can provide UX similar to Native application even with Web application.

Since there are things that I can not introduce this time, I will write again if I have the opportunity.

Service Workers

  • Cache Control
  • Offline Page

Push Notifications

  • Token Refresh
  • Firebase Cloud Messaging