In this article, you will find out how to construct a PWA (Progressive Web Application) on the Vue.js. Let’s start the article by giving you an insight into Vue PWA. 

Vue is one of the top JavaScript frameworks that was created in 2016 and has made significant progress in the high-end Single-page Applications

In 2022 almost 66% of developers were interested in this JavaScript framework. This solid framework has 170K stars on GitHub and is projected to become the 5th most starred project on it.

What makes it so well-liked? Because it owns everything that could be required to make sure that the development process is effortless and uncomplicated. 

This would include a significantly lightweight, modular, gentle learning curve combined with the flexibility that is all encompassed within the Vue Framework, making it a perfect platform for the creation of Vue PWA. 

Overview of PWA

PWA or progressive web application has been commonly called a type of application software created using JavaScript, HTML, and CSS. 

The most noteworthy thing about a progressive web app is that it can be utilized by any platform that uses any standard compilation browser. Its creation can be credited to Alex Russel at Google in 2015. 

They are known to cut out the need for any e-commerce vendors for the development of native apps for multiple mobile operating systems. Therefore many businesses connect with Vue js Development company to get their job done and achieve robust native app solutions.

It completely cuts out the need for an end-user to open the app store. Instead, the download or purchase will be made locally. 

One of the most famous online shopping portals, Alibaba, came out with its own PWA in the year 2016 and had a solid $15.69 billion in revenues

It was telling you that PWA helped them in making far more web conversions than initially predicted. A PWA mixes the best of generic web development and mobile UX’s speed and reliability. 

Benefits of a PWA(With Awesome Statistics)

To fully understand the benefits of a PWA, its statistics must be stated. Talking about companies that have employed it over the years are mentioned below- 

  • The company Forbes’s PWA test showed an increase in user session length by almost two times more. 
  • They also saw an increase in the completion rate by almost six times more, along with 20% added impressions. It single-handedly managed to reduce the load time from 3 or 12 seconds to 0.8 seconds. 
  • Pinterest recently recreated their websites accessible to mobiles as a PWA as well as the core engagements. 
  • It subsequently increased by 60%, along with a growth in the user-generated ad revenue by 44%. Their PWA web app saw a surge of 40% in the time spent by users on it. 
  • Dating apps like tinder managed to cut their load time to 4.69 seconds from their previous load time of 11.91 seconds using their PWA. 
  • This PWA created was 90% smaller than its native android app. It led to an increase in user engagement across the board. 
  • The microblogging and social networking website Twitter following its PWA creation gained an increase of 65% in their pages per session coupled with a rise of tweets by 75%. 
  • It also managed to lower the bounce rate and added light loads that were achieved in under 3 seconds compared to its previous records. 
  • The company Trivago and its users saw a growth of 150% when the PWA was added to home screens. This behavior led to a subsequent increase of 97% in the engagement as well, thereby leading to increased clicks outs to the hotels and other offers. 

These examples of top companies tell us that a PWA could help a business attain widespread

  • They have a low usage threshold when putting into use.
  • Do not rely on any app stores and are quite independent.
  • Can be added to the home screen and accessed on smartphones with ease.
  • All the content on a PWA app is counted in search engine optimization results.
  • They are much cheaper in creation than the average app.

The benefits steer into the direction of higher conversions and revenues! 

Why Build Vue Into PWA?

Using Vue for making progressive web applications is used for getting a hold of one and only one feature, and that is Nuxt. 

Vue.js in itself was not created for aiding in the creation of PWA’s generally. However, it is quite possible that this development could be because of the recent popularity Vue seems to have gained. 

Talking about Nuxt, it must be told that Nuxt offers features that are out of the box and can be altered to suit the needs of the project better. 

It allows the making of universal apps without much effort or even a server. Vue JS PWA  can be created successfully with much pain just by the one feature, Nuxt.

These features, mixed with those of a PWA, can ensure the development applications that are perfect for any business organization. They can be made completely free of cost. 

Converting Vue App into a PWA

The Base App

A base app is essentially a platform for the development of apps. A sort of software remedy to get a boost in order to create a custom app. 

Here the base app is the Vue.js app that utilizes firebase for database and authentication. Source code can be attained to quicken the process.  

Start by using a git clone command and then downloading the code in the system from GitHub link provided here- rb.gy/vzoyyo

If you are unfamiliar with how to download the code, then all you have to do is 

Step 1- Click on the Code icon, highlighted in green. 

Step 2- From the two options that pop up on clicking it and click on ‘download as ZIP”. 

Once you are through with these steps, continue to launch the command terminal after the install command using Yarn or NPM much be made. 

npm install // or yarn install

As the installation of packages completes a folder by the name .node_modules  will have set up in the apps folder. 

If you wish to check the working of the app, then try launching it on your browser. You can do so by giving the command run npm run dev or yarn dev  

The Manifest File

The browser must know of the Vue JS PWA that is being created. For this, you must start by creating a Web App Manifest that is a JSON file. It is responsible for defining information about the app. 

The file created will look a lot like that on an Android manifest file and even possess similar information like the author and name. 

Now you must construct a file by the name manifest.json within the root directory of the project. The metadata below can help you describe the app- 

{

  "name": "DC-Covers",

  "short_name": "Covers",

  "start_url": "index.html",

  "display": "standalone",

  "theme_color": "#0476F2",

  "background_color": "#fff",

  "icons": [

    {

      "src": "", // usually kept in the static/icons folder

      "sizes": "", // enter the size of the image 

      "type": "" // enter the type of the image eg: image/png,

    },

  ]

The name in this metadata is DC-Covers, and the short_name would be Covers. This property can be skipped if the name of your app is short. 

There will be a property that is cited by the name start_url and refers to the HTML file in the app. In the above case, the main file will be index.html. 

After this using the display properties command to the browser, this command communicates how to open the app. The property can be set to Fullscreen or minimalui. Here the standalone value will ensure the app opens like a regular app. 

The theme_color command is utilized to put color on the toolbars of the mobile. At the same time, the background_color command will add color to the PWA splash screen. 

The icons property is used to define the icons of the app that is trying to be created. After this, all you must do is open the index.html file and then add a link tag to it that will point in the direction of the manifest.json file. 

<html>

  <head>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css" />

    <link rel="manifest" href="/manifest.json"/>

    <title>DC Comics Rebirth - Covers</title>

  </head>

  <body>

    <div id="app"></div>

    <script src="/build/build.js"></script>

  </body>

</html>

To check if your code has worked perfectly then, you have to open DevTools on the browser. Once opened, you will see a tab by the name Application, and you will see something like the image below.   

Meta Tags

Meta tags are bits of texts or write-ups that can aptly express all the content of a page. They cannot pop up on their own but are present in the source code. 

You can add them aside from the web app manifest file to ensure high-quality information. This will aid browsers like Microsoft Edge or iOS. 

For the installation within the index.html file, you must write the subsequent meta tags in the head component. 

<meta name="apple-mobile-web-app-capable" content="yes">

<meta name="apple-mobile-web-app-status-bar-style" content="default">

<meta name="apple-mobile-web-app-title" content="DC-Covers">

<meta name="msapplication-TileImage" content="link to the image in static folder">

<meta name="msapplication-TileColor" content="#000">

For iOS browsers- 

The very first three tags denote that the iOS web app can be installed, and the tag will configure the manner of the status bar. 

You can set your user status bar to default. The very last tag will be able to narrate iOS the title of the app. 

For Microsoft Edge browsers-  

To define the meta tags for Microsoft Edge browsers, you must direct smaller icons to the static/icons folder that are stored within. 

TitleColor tag will be able to define the title color. Windows will be used to place an icon on its home screen. A link must be added to this icon that will be displayed on the home screen. See the image below to understand. 

<link rel="apple-touch-icon" href="link to the smaller icon">

Caching With Service Workers

Service Workers are a class of web workers that is actually a JavaScript file that can run independently from the main browser’s thread. 

They make up the very core of Vue JS PWA techniques for push notifications as well as resource caching. There are scripts that are present in the backdrop and can make a clear distinction between web apps and web pages. 

The service workers come into play to implement features that cut out the need for user interaction. It is also responsible for being the platform on which multiple features can rely on. 

There is usually a requirement for every task to have a separate service worker; it can be a bit tedious and monotonous. 

So, you can employ the sw-precache to make the process automated. For that, you are required to install sw-precache by using NPM globally: 

$ npm install sw-precache -g

Write the code you see below after creating a configuration file by the name sw-config.js. 

module.exports = {

  staticFileGlobs: [

    'index.html',

    'manifest.json',

    'dist/**.js'

  ]

}

The file is a way of delegating that caching of index.html, manifest.json, along with other JavaScript files that may be stored in the dist folder. 

After this, run command sw-precache and –config flag that is linked to sw-config.js as you see below-

$ sw-precache --config sw-config.js

Following this, a new file by the name service-worker.js will be created. This file will contain code that defines the service worker that will be responsible for caching the file above. Keep in mind this process is to initiate a manual generation of server workers. 

Automate Server Worker Generation

To make sure the server worker process is automated and not manual inside the build process, you must follow this. 

It can be done by utilizing the sw-precache-webpack-plugin as a developer dependency. Start off by installing the package as a devDependency- 

$ npm install -D sw-precache-webpack-plugin

After this, you must open the webpack.config.js file and continue to import devDependency. See below to understand how- 

const SWPrecache = require('sw-precache-webpack-plugin')

You will observe an if statement at the bottommost, this statement defines plugins that are used in the app. 

Continue to write a new instance of SWPrecache inside. See the code below to understand how- 

new SWPrecache({

  cacheId: 'dc-covers',

  filepath: 'service-worker.js',

  staticFileGlobs: [

    'index.html',

    'manifest.json',

    'dist/*.{js,css}

  ],

  stripPrefix: '/'

})

The npm run build command must be run, and then you will notice a file named service-worker.js will be created. After this, you must register the service worker into the browser. 

Service Worker Registration

Once you are done with creating the service worker, you must now shift focus on registering it on the browser. The easiest way to get this done is by registering a code within the src/main.js file. 

The main.js file a navigator API must be used because it possesses property named serviceWorker coupled with a register method. 

This method will acquire the URL of the file that takes up the name serviceworker.js. It must be taken care of that the browser supports the service workers. 

Checking this is important because if the browser does not support the service worker, then there is no purpose in running the registration. 

Since the service worker gets generated once the production is initiated in the app, so, make sure you only run the code when the production mode gets started in the app. 

const prod = process.env.NODE_ENV === 'production'

const shouldSW = 'serviceWorker' in navigator && prod

if (shouldSW) {

  navigator.serviceWorker.register('/service-worker.js').then(() => {

    console.log("Service Worker Registered!")

  })

}

Reconstruct the app by employing npm run build and launching it using http-server or via Live Server extension of the VS code. 

Giving the application section a look on browsers’ devtools will tell you that the service workers section is not empty now. 

Once the process of service worker registration is complete, then the app will cache the static files. 

However, since the development is still in process, caching doesn’t permit any visible changes in the app. 

This is because the service worker updates everything by comparing the modified and old versions. If there is a difference in the modified version, it simply changes the old version. 

So, running it on the browser will show no changes you made when the service worker was in control of the cache. The control usually lasts for one hour. 

Unregistered Service Worker

You can do the unregistering of the service worker just like its automation process. The unregistering process comes in handy when the creator does not want the service worker to cache anything at all. 

You can easily do it by first creating a fresh service worker for the development mode, creating a file, and naming it service-worker-dev.js. 

This fresh creation of the service worker will overwrite the original one created during the production mode. Add eventListener in the install event. 

It calls a function that, in turn, calls skipWaiting. Doing so will forcefully activate the service worker. 

self.addEventListener('install', () => {

  self.skipWaiting()

})

Here, you can add another eventListener for the activate event, and it will help you access all other windows and tabs in the browser that utilizes the service worker. 

self.addEventListener('activate', () => {

  self.clients.matchAll({

    type: 'window'

  }).then(clients => {

    for (let client of clients) {

      client.navigate(client.url)

    }

  })

})

You need to use this service worker in the previous section, by adding a main.js file to it.  

const shouldSWDev = 'serviceWorker' in navigator && !prod

Now, add an else if to the if statement you had used in the earlier sections. It will check if the production is not in mode. 

else if (shouldSWDev) {

  navigator.serviceWorker.register('/service-workder-dev.js').then(() => {

    console.log('Service Worker Registered!')

  })

}

Run the app by using npm run dev, and in the DevTools in the Vue JS PWA application section, you will see the service worker file has been modified. 

Building a Vue PWA with Nuxt

The steps mentioned below will help you in creating a PWA Vue easily. 

Pre-requisites

You need to know two main prerequisites to build a Vue PWA easily fluently. They are- 

Number 1- A basic understanding of the Nuxt.js 

Number 2- A snipcart account 

Creating a Nuxt Project

To start your work on Nuxt is fairly easy, and that is because of the create-nuxt-app script. You must run the command on the terminal- 

npx create-nuxt-app snipcart-nuxt-pwa

A thing that must be kept in mind here is that the npx must be available out of the box if your NPM range is 5.2.0 or higher. 

Once the prompt pops up, go along with the installation instructions in the terminal. There is no need to worry about the installation of the Vue PWA module as it can be added later. 

On answering all the questions, your project directory structure will be all set. There will be an installation on Sass, along with sass-load, as a development dependency. It will do so seamlessly with Nuxt. 

npm i -D node-sass sass-loader

Installation of front matter-markdown-loader to retrieve any content from the guides or products in the markdown files. 

The installation of the module will also allow the retrieving of front-matter files present in the JS object. 

 npm i -D frontmatter-markdown-loader

You have now reached a stage that you must update the nuxt.config.js file, see the snippet below- 

...

css: [

  '@/assets/<your_sass_entrypoint>'

],

...

build: {

  extend(config, ctx) {

    config.module.rules.push({

      test: /.md$/,

      loader: 'frontmatter-markdown-loader',

      include: path.resolve(__dirname, 'contents'),

    })

  }

}

...

On the completion of the above process, you can serve the project locally by using the command npm run dev. After this visit, the URL localhost:3000 on the browser. 

Adding the content to Web App

One needs to import the content out of the web app as a precursory step, and there are multiple ways to do it. This step can be skipped if you are querying for an API. 

In the demonstration, there is a use of markup to put all your files within the content/guides directory. 

You can also create a guide.js in the same directory, follow the code below to learn how- 

export default [

  'preparing-for-the-apocalypse',

  'all-about-weapons'

]

You can retrieve all the articles on the website programmatically using this array, but you will have to rename them. Please give them a name of choice and keep updating as they have newer entries.  

Creating Pages and Components

This step will involve creating two pages; one of them will be a home page that presents the list of survival guides. Along with this, some pages read the entire guide. 

For this process to go smoothly, you must start by modifying the layout and add a header and footer to it.

Open the default.vue file that is within the layouts directory. Following the code below will help add the file-  

<template>

  <div class="main">

    <Header />

    <nuxt />

    <Footer />

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

    <script

      id="snipcart"

      src="https://cdn.snipcart.com/scripts/2.0/snipcart.js"

      data-api-key="<YOUR_API_KEY>"

    ></script>

  </div>

</template>

<script>

import Header from "~/components/Header.vue";

import Footer from "~/components/Footer.vue";

export default {

  components: {

    Header,

    Footer

  }

};

</script>

A personalized Header.vue or Footer.vue component in the components directory. You can useSnipcart’s JS file along with its dependencies to use its style sheet, you must incorporate it in the nuxt.config.js file. 

...

link: [

  { rel: 'stylesheet', href: 'https://cdn.snipcart.com/themes/2.0/base/snipcart.min.css' }

]

...

In order to create the homepage, you must edit the index.vue, which is in the pages directory. You can do so by following the code you see below. 

<template>

  <div class="main">

    <main>

      <div>

        <article class="post" v-for="(guide, index) in guides" :key="index">

          <div class="post-aside">

            <small>{{ guide.attributes.date }}</small>

            <h3 class="post-title"><nuxt-link :to="guide.attributes.link">{{ guide.attributes.title }}</nuxt-link></h3>

            <p>{{ guide.attributes.description }}</p>

          </div>

          <div class="products">

            <article v-for="(product, index) in guide.attributes.products" :key="index">

              <img :src="product.image" :alt="product.name">

              <button

                class="buy-button snipcart-add-item"

                :data-item-id="product.sku"

                :data-item-name="product.name"

                :data-item-price="product.price"

                :data-item-image="product.image"

                :data-item-url="`https://snipcart-nuxt-pwa.netlify.com/`">

                {{`$${product.price}`}}

              </button>

              <p class="product-name">{{product.name}}</p>

            </article>

          </div>

        </article>

      </div>

      <Testimonals />

    </main>

  </div>

</template>

<script>

import guides from '~/contents/guides/guides.js'

import Testimonials from '~/components/Testimonials'

export default {

  components: {

    Testimonials,

  },

  async asyncData ({ route }) {

    const promises = guides.map(guide => import(`~/contents/guides/${guide}.md`))

    return { guides: await Promise.all(promises) }

  },

  head() {

    return {

      title: "All posts | Nuxt.js PWA survival store"

    }

  }

}

</script>

You can easily import all your lists from the guides; furthermore, retrieving markup, and attributes can also take place within the asyncData function. 

You need to call the function on the server at generation or before the loading of pages. This ensures the safekeeping of all the content in the guide and is out of reach of crawlers. 

Keynote- asyncData function is available only for the pages and not the components. 

You can create Pages for guides now by using the guides directory within pages, name the file _slug.vue. 

<template>

  <div class="single-post">

    <h1>{{ attributes.title }}</h1>

    <p>{{ attributes.date }}</p>

    <span v-html="html" class="markdown"></span>

    <div class="products">

      <article v-for="(product, index) in attributes.products" :key="index">

        <img :src="`../${product.image}`" :alt="product.name" />

        <button

          class="buy-button snipcart-add-item"

          :data-item-id="product.sku"

          :data-item-name="product.name"

          :data-item-price="product.price"

          :data-item-image="product.image"

          :data-item-url="`https://snipcart-nuxt-pwa.netlify.com${currentUrl}`"

          >{{`$${product.price}`}}</button>

        <p class="product-name">{{product.name}}</p>

      </article>

    </div>

    <Bio />

  </div>

</template>

<script>

import Bio from "~/components/Bio";

export default {

  components: {

    Bio,

  },

  layout: "guide",

  async asyncData({ params, route }) {

    const guideName = params.slug

    const markdownContent = await import(`~/contents/guides/${guideName}.md`)

    return {

      attributes: markdownContent.attributes,

      html: markdownContent.html,

      currentUrl: route.path

    };

  },

  head() {

    return {

      title: `${this.attributes.title} | Nuxt.js PWA survival store`

    }

  }

};

</script>

The name is _slug to make sure you are able to construct dynamic routes. Import a markdown file by the name params.slug variable within the asyncData function. 

You can modify the template of this file for Vue JS PWA as per the need. If you plan to publish the site with the npm generate command, you must add the code you see below into the configuration file. 

import guides from "./contents/guides/guides.js"

...

/*

** Generate dynamic routes

*/

generate: {

  fallback: true,

  routes: [].concat(guides.map(guide => `guides/${guide}`))

},

...

It is important to specify this; otherwise, Nuxt will not automatically generate the index pages. Nuxt requires all of its functions to be specified for its proper functioning.  

Turning SPA into PWA

The process of turning the web application into a Vue PWA is one of the easiest possible steps. For this, you should start by installing the Vue JS PWA module.

npm i @nuxtjs/pwa

Now move on to add it to the configuration file created- 

...

modules: [

  '@nuxtjs/pwa',

],

...

There is an option to overwrite the value of the manifest. You can do so by following the code mentioned below- 

...

manifest: {

  name: 'Nuxt.js PWA survival store',

  short_name: 'Nuxt.js PWA',

  lang: 'en',

  display: 'standalone',

},

...

Note that display standalone is what will allow the Vue PWA to open on its personal window without the need for browser navigation. 

The property is necessary to install Vue PWAon certain platforms like Google Chrome on the desktop. If you want to cache, then you must specify assets from the external domains. 

Once you have followed the process thoroughly, your PWA should be fully functional. It will be able to work on any whatsoever desktop or mobile platform. 

workbox: {

  runtimeCaching: [

    {

      urlPattern: 'https://fonts.googleapis.com/.*',

      handler: 'cacheFirst',

      method: 'GET',

      strategyOptions: { cacheableResponse: { statuses: [0, 200] } }

    },

    {

      urlPattern: 'https://fonts.gstatic.com/.*',

      handler: 'cacheFirst',

      method: 'GET',

      strategyOptions: { cacheableResponse: { statuses: [0, 200] } }

    },

    {

      urlPattern: 'https://cdn.snipcart.com/.*',

      method: 'GET',

      strategyOptions: { cacheableResponse: { statuses: [0, 200] } }

    },

    {

      urlPattern: 'https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js',

      handler: 'cacheFirst',

      method: 'GET',

      strategyOptions: { cacheableResponse: { statuses: [0, 200] } }

    }

  ]

}

Hosting a PWA on Netlify

Once your creation of the Vue PWA is complete, you will definitely want to publish this PWA app online. How do you do it? With the help of Netlify. 

This hosting service makes the hosting of Nuxt PWA effortless. To complete the job, you will have to put the project directory on GitHub, Gitlab, and also BitBucket if you haven’t already done it. 

After this, you need to head out to Netflix and log into your account and then link it with the repository. 

If the process goes smoothly, you will receive a prompt, and then you must add npm run generate as a building command and then dist as a publishing directory. 

Your website will be accessible at the address specified once the build is fully complete. Also, all the changes you have pushed to the repository’s master branch will undoubtedly update your PWA as well. 

Conclusion

This article brought the idea of utilizing Nuxt.js for the development of PWA applications. It is a wholesome platform that will ensure there is everything available to a programmer. 

Your idea may be strange, but the process will be worth it. Finding the best possible way to ensure the PWA is installable on the browsers will be time-consuming, but for this, GitHub will come to your rescue. 

Apart from that, the combination of Vue PWA could be exemplary.

We hope you had a great time reading this article and it will definitely be helpful if you hire vue js developers for enhanced Progressive Web App Development.

Chintan Gor

CTO, eSparkBiz

Enthusiastic for web app development, Chintan Gor has zeal in experimenting with his knowledge of Node, Angular & React in various aspects of development. He keeps on updating his technical know-how thus pinning his name among the topmost CTO's in India. His contribution is penned down by him through various technical blogs on trending tech. He is associated with eSparkBiz from the past 11+ years where one can get premium services.