Search code examples
vue.jsprogressive-web-apps

beforeinstallprompt not trigger within a PWA's Vue app


I've installed a PWA app using the vue cli standards. After that, I've simply add the code provided by this guide.

But when I access to http://localhost:8080/ , nothing is triggered.

Here's the App.vue code:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="PWA Test"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

let deferredPrompt;

function showInstallPromotion() {
  alert("ciao");
  console.log(deferredPrompt);
}

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  created() {
    window.addEventListener('beforeinstallprompt', (e) => {
      alert("beforeinstallprompt");

      // Prevent the mini-infobar from appearing on mobile
      e.preventDefault();
      // Stash the event so it can be triggered later.
      deferredPrompt = e;
      // Update UI notify the user they can install the PWA
      showInstallPromotion();
    });
  },
  mounted() {
    if("serviceWorker" in navigator) {
      navigator.serviceWorker.register("service-worker.js").then(reg => {
          console.log("Registration succesful, scope: " + reg.scope);
      })
      .catch(err => {
          console.log(err);
      })
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Manifest problem? I believe its respected using the vue cli. How can I check if the manifest is ok and I'm ready for a PWA app? First steps on this world, where am I wrong? Thanks

Here's the manifest.json (within public folder) I have:

{
  "name": "vuejspwa",
  "short_name": "vuejspwa",
  "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": "fullscreen",
  "background_color": "#000000",
  "theme_color": "#4DBA87"
}

Solution

  • You need to meet first some critera to make your app installable.

    The criterias are:

    • App is not already installed
    • Be served over HTTPS (but should work in localhost with HTTP aswell)
    • Includes a Web app manifest

    The manifest looks like this:

    //manifest.webmanifest
    
    {
      "name": "My App",
      "short_name": "MA",
      "start_url": ".",
      "display": "standalone",
      "icons": [
      {
        "src": "images/touch/homescreen192.png",
        "sizes": "192x192",
        "type": "image/png"
      },
      {
        "src": "images/touch/homescreen512.png",
        "sizes": "512x512",
        "type: "image/png"
      }]
    }
    

    Thats the minimal amount you need. and then include it in your header:

    <link rel="manifest" href="/manifest.webmanifest">
    
    • Register service worker with fetch handler.

    So how do register the worker?

    Well you use vue.js so mounted() is a good place to put it in:

    //check if service worker is available in browser
    
    if("serviceWorker" in navigator) {
       navigator.serviceWorker.register("path/to/service-worker.js").then(reg => {
          console.log("Registration succesful, scope: " + reg.scope);
       })
       .catch(err => {
          console.log(err);
       })
    }
    

    You need to provide the path to your worker as shown in the example above. The service worker is just a tiny javascript file.

    The requirements says you need a fetch handler, so lets create one:

    //service-worker.js
    
    self.addEventListener('fetch', function(event) {
      event.respondWith(fetch(event.request));
    });
    

    Thats it.

    This caching approach is called "network only" because you only load the ressources from the network instead of the cache.

    Well actually it isnt a caching approach because you dont cache anything, however there are also "offline first" strategies. I recommend this site here, it shows many strategies and how you can use it.

    https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook