How to build PWA w/ Vue CLI 3 (Service Workers / Add to Home Screen / Push Notifications)
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
PWA — Service Workers
If you start with npm run serve
, Service Workers will not work as follows.
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 serve
when you don’t use Service Workers)
$ npm run build
DONE Build complete. The dist directory is ready to be deployed.
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
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
- Create a new project on Firebase
At first sign in to Firebase console with Google account, and create a new project.
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
- Configure Web Credentials with FCM
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
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.
7. Receive Test Message via cURL
$ 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
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