Showing posts with label vue.js. Show all posts
Showing posts with label vue.js. Show all posts

Sunday, July 24, 2022

How to watch the change in arrays and objects in VueJs

In this tutorial, we will learn how to watch the nested data like arrays and objects in Vue.js

Watching Props Arrays:

export default {
  name: "ComponentName",
  props: {
    users: {
      type: Array,
      required: true,
    },
  },
  watch: {
    users: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      }
    }
  },
}

Here we are using the users array and watching it inside the watch block. deep: true will let Vue to watch inside the array and the handler will give the old and new values.

Watching Objects:

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  watch: {
    entity: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      }
    }
  },
}

Here, we are creating the entity object and watching it in the watch block. Here it will deep watch the whole entity object.

Watching properties of Objects:

If we don't want to watch for every change on the object, we can watch every single entity as well

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  watch: {
    'entity.properties': {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
      deep: true
    },
    'entity.propertyOne': {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
    },
  },
}

Watching properties of Objects using computed:

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  computed: {
    entityPropertyOne() {
      return this.entity.propertyOne;
    }
  },
  watch: {
    entityPropertyOne: {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
    },
  },
}
Share:

Friday, January 14, 2022

How to remove hash mode(#) from URL in VueJs application

This is a quick tutorial on how we can get rid of hash mode(#) from the URL in the Vue.js application

While using Vue router, the default mode is a hash mode. So when the user tries to load the page like http://localhost:8080/invalid/url then it will redirect to the base URL with hash.

We can simply remove hash mode by adding history mode while initializing the Vue router

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

This initialization can be found under folder >> src >> router >> index.js if we initialized the application with router setup using Vue CLI. Or in main.js file.

Once we remove the hash mode the user with an invalid URL might get a 404 not found error. For this, we need to manage the configuration in the server where we deploy the application.

For this, we need to configure in such a way that for the invalid users, we will redirect the user to index.html page which will open the base URL of the application.

In Nginx

location / {
  try_files $uri $uri/ /index.html;
}

In Apache

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</IfModule>

In Firebase inside firebase.json add the following JSON config

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

For more server configuration please visit the vue-router page.

Share:

Adding global CSS in VueJs application

This is a quick tutorial on how we can add the global CSS in the Vue.js application.

In each Vue.js component, we can add the component-based CSS which means the CSS will only be applicable for that component.

This can be done by using the scoped keyword in style tag inside the component as below:

<template>
   <div>
    </div>
</template>

<script>
  
</script>

<style scoped>
    /*add your css here*/
    
</style>

If we have the common CSS, we need to use a global CSS file to add it and use the class name inside the HTML element inside components.

For this, let's create a css folder under src >> assets and add a main.css file. This file will contain all the global CSS.

Now, we need to import the created CSS file; which can be done under the main.js file. Import the file as below

import './assets/css/main.css';

If we want to add multiple global CSS files we can simply add the file and import it in main.js as described.

Share:

Change the HTML title tag and favicon icon on newly created VueJs application

This is a quick tutorial on how we can change the HTML document title and favicon in the Vue.js application

If we are creating the VueJs application with Vue CLI then it will automatically import the project name as HTML title and default VueJs favicon icon.

To change this, go to the project directory, we can see the public folder there we can find the index.html file if we open the file we can see the title tag as below:


<title><%= htmlWebpackPlugin.options.title %></title>

Simply remove the dynamically imported content inside the tag and add the desired title to it

<title>360learntocode</title>

Now let's change the default favicon. For this, go to the same public directory where we can see the favicaon.icon.

Simply replace your favicon icon here with the same name or if we want to use it with a different name then change the name inside index.html file

<link rel="icon" href="<%= BASE_URL %>360learntocode.ico">
Share:

Thursday, January 13, 2022

How to use share functionality using web share API in VueJs application

In this tutorial, we are going to implement the web share functionality using Web Share API.

Web Share API is not supported for all browsers. We can see the supported browser for this API from caniuse.


Please follow the tutorial for sharing on social media platforms.

The Web Share API provides a mechanism for sharing links, text, files, and other content utilizing the sharing mechanisms of the underlying operating system. Note that this API only can be used over the secure connection HTTPS.

Sharing Links and Text Description

Let's create a sample vue component called Share.vue and add the following HTML inside the template which contains a simple button to allow users for sharing.

<div class="share" v-if="isSupported">
    <button class="button" @click="webShare">Share</button>
</div>
.button {
  background-color: #4CAF50;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
}

Here, if the browser supports the API, we are rendering the share button to allow the user to share. If not then we are hiding the button. Now, let's add the data and method used

created() {
    this.isSupport();
  },
  data () {
    return {
      isSupported : false,
      url : "https://caniuse.com/web-share",
      title:"Web API Share",
      description: "Web API Sharing"
    }
  },
  methods: {
    isSupport() {
      if (navigator.share) {
        this.isSupported = true;
      }
    },
    webShare() {
      let self = this;
      navigator.share({
        title: self.title,
        text: self.description,
        url: self.url
      })
    }
  }
}

webShare function allows the user to share link and title and description on different applications of OS.

Sharing Files

webShare() {
      let self = this;
      fetch("file_url").then(function (response) {
        return response.blob()
      }).then(function (blob) {
        let file = new File([blob], "picture.jpg", {type: 'image/jpeg'});
        let filesArray = [file];
        if (navigator.canShare && navigator.canShare({files: filesArray})) {
          navigator.share({
            title: self.title,
            text: self.description,
            files: filesArray,
            url: self.url
          });
        }
      });
    }

If we want to share the file, first load the file and test whether the file can be sharable or not, if it is sharable then it will be shared over the available supported application of OS.

The overall implementation looks as below:

<template>
    <div class="share" v-if="isSupported">
        <button class="button" @click="webShare">Share</button>
    </div>
</template>

<script>
    export default {
        name: "Share",
        created() {
            this.isSupport();
        },
        data () {
            return {
                isSupported : false,
                url : "https://www.360learntocode.com/2022/01/how-to-implement-social-media-share.html",
                title:"Web API Share",
                description: "Web API Sharing"
            }
        },
        methods: {
            isSupport() {
                if (navigator.share) {
                    this.isSupported = true;
                }
            },
            webShare() {
                let self = this;
                navigator.share({
                    title: self.title,
                    text: self.description,
                    url: self.url
                })
            }
        }
    }
</script>

<style scoped>
    .button {
        background-color: #4CAF50;
        border: none;
        color: white;
        padding: 15px 32px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 16px;
        margin: 4px 2px;
        cursor: pointer;
    }
</style>
Share:

Sunday, January 9, 2022

Create UTC count down timer in VueJs

In this tutorial, we are going to learn how to create a UTC countdown timer in VueJs. We are UTC time to manipulate the countdown timer so that every user from different locations can see the same countdown.

Let's create a component called CountDownTimer.vue

Now, let's add some HTML and CSS for the countdown timer in the template.

<div v-if="displayCountDown">
    <h2 class="text-animation" v-if="isLive">Sale is now LIVE</h2>
    <div v-else>
        <h2 class="text-animation">Sale starts in:</h2>
        <section>
            <section class="timer">
                <div>
                    <section>
                        <p>{{ days }}</p>
                        <p>
                            <small>Days</small>
                        </p>
                    </section>
                    <span>:</span>
                    <section>
                        <p>{{ hours }}</p>
                        <p>
                            <small>Hours</small>
                        </p>
                    </section>
                    <span>:</span>
                    <section>
                        <p>{{ minutes }}</p>
                        <p>
                            <small>Minutes</small>
                        </p>
                    </section>
                    <span>:</span>
                    <section>
                        <p>{{ seconds }}</p>
                        <p>
                            <small>Seconds</small>
                        </p>
                    </section>
                </div>
            </section>
        </section>
    </div>
</div>
<style scoped>
    .timer {
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .timer div:first-child {
        border: 1px solid white;
        border-radius: 3px;
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        text-align: center;
        margin-bottom: 1em;
        padding: 1em 1em 0 1em;
    }

    section p:first-child,
    .timer div:last-child span {
        display: contents;
    }

    @media screen and (max-width: 480px) {
        .timer div:last-child {
            margin-left: 2em;
            margin-right: 2em;
        }
    }

    .text-animation {
        animation: color-change 5s infinite;
        font-weight: 400;
    }

    @keyframes color-change {
        0% {
            color: #00FFA3;
        }
        25% {
            color: yellow;
        }
        50% {
            color: #DC1FFF;
        }
        75% {
            color: #F1A945;
        }
        100% {
            color: #00FFA3;
        }
    }
</style>

Add the data used inside the template

data() {
    return {
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 0,
      isLive: false,
      displayCountDown: false
    }
  },

Create a function called startTimer where we are going to add the timmer logic.

methods: {
    startTimer() {
      const countdownDate = new Date("January 11, 2022 7:59:00").getTime(); // always use UTC time
      let self = this;
      let interval = setInterval(() => {
        const now = new Date();
        let nowUTC = new Date(
            now.getUTCFullYear(),
            now.getUTCMonth(),
            now.getUTCDate(),
            now.getUTCHours(),
            now.getUTCMinutes(),
            now.getUTCSeconds()
        ).getTime();
        const distance = countdownDate - nowUTC;
        const days = Math.floor(distance / (1000 * 60 * 60 * 24));
        const hours = Math.floor(
            (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
        );
        const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
        const seconds = Math.floor((distance % (1000 * 60)) / 1000);
        if (distance <= 0) {
          self.isLive = true;
          clearInterval(interval);
        } else {
          self.days = days;
          self.hours = hours;
          self.minutes = minutes;
          self.seconds = seconds;
        }
        self.displayCountDown = true;
      }, 1000);
    }
  }

Here, first, create the UTC time when the action will happen i.e for e.g the time when the sale starts. Make sure that the time needs to be UTC time.

const countdownDate = new Date("January 11, 2022 7:59:00").getTime(); // always use UTC time

After that, we are using setInterval() method which repeatedly calls a function or executes a code snippet inside it, with a fixed time delay between each call.

Note there we are using 1000 ms time so that the countdown will refresh in every second.

Let's look into the below code

 const now = new Date();
        let nowUTC = new Date(
            now.getUTCFullYear(),
            now.getUTCMonth(),
            now.getUTCDate(),
            now.getUTCHours(),
            now.getUTCMinutes(),
            now.getUTCSeconds()
        ).getTime();

We are getting the current data which gives the current location browser data. We have to convert this to UTC current date. So the user from a different location can see the same countdown

After that, we are calculating distance which will show the countdown is expired or not and days, hours, minutes, and seconds.

If the countdown is expired then we are clearing the setInterval and hiding the countdown and showing some desired text

Start the countdown timer. For this, simply call the startTimer function from created hook.

created() {
    this.startTimer();
  },

The demo output for this example looks like below:


The overall code implementation looks as below:

<template>
    <div v-if="displayCountDown">
        <h2 class="text-animation" v-if="isLive">Sale is now LIVE</h2>
        <div v-else>
            <h2 class="text-animation">Sale starts in:</h2>
            <section>
                <section class="timer">
                    <div>
                        <section>
                            <p>{{ days }}</p>
                            <p>
                                <small>Days</small>
                            </p>
                        </section>
                        <span>:</span>
                        <section>
                            <p>{{ hours }}</p>
                            <p>
                                <small>Hours</small>
                            </p>
                        </section>
                        <span>:</span>
                        <section>
                            <p>{{ minutes }}</p>
                            <p>
                                <small>Minutes</small>
                            </p>
                        </section>
                        <span>:</span>
                        <section>
                            <p>{{ seconds }}</p>
                            <p>
                                <small>Seconds</small>
                            </p>
                        </section>
                    </div>
                </section>
            </section>
        </div>
    </div>
</template>

<script>
    export default {
        name: "CountDownTimer",
        created() {
            this.startTimer();
        },
        data() {
            return {
                days: 0,
                hours: 0,
                minutes: 0,
                seconds: 0,
                isLive: false,
                displayCountDown: false
            }
        },
        methods: {
            startTimer() {
                const countdownDate = new Date("January 11, 2022 7:59:00").getTime();
                let self = this;
                let interval = setInterval(() => {
                    const now = new Date();
                    let nowUTC = new Date(
                        now.getUTCFullYear(),
                        now.getUTCMonth(),
                        now.getUTCDate(),
                        now.getUTCHours(),
                        now.getUTCMinutes(),
                        now.getUTCSeconds()
                    ).getTime();
                    const distance = countdownDate - nowUTC;
                    const days = Math.floor(distance / (1000 * 60 * 60 * 24));
                    const hours = Math.floor(
                        (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
                    );
                    const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
                    const seconds = Math.floor((distance % (1000 * 60)) / 1000);
                    if (distance <= 0) {
                        self.isLive = true;
                        clearInterval(interval);
                    } else {
                        self.days = days;
                        self.hours = hours;
                        self.minutes = minutes;
                        self.seconds = seconds;
                    }
                    self.displayCountDown = true;
                }, 1000);
            }
        }
    }
</script>

<style scoped>
    .timer {
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .timer div:first-child {
        border: 1px solid white;
        border-radius: 3px;
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        text-align: center;
        margin-bottom: 1em;
        padding: 1em 1em 0 1em;
    }

    section p:first-child,
    .timer div:last-child span {
        display: contents;
    }

    @media screen and (max-width: 480px) {
        .timer div:last-child {
            margin-left: 2em;
            margin-right: 2em;
        }
    }

    .text-animation {
        animation: color-change 5s infinite;
        font-weight: 400;
    }

    @keyframes color-change {
        0% {
            color: #00FFA3;
        }
        25% {
            color: yellow;
        }
        50% {
            color: #DC1FFF;
        }
        75% {
            color: #F1A945;
        }
        100% {
            color: #00FFA3;
        }
    }
</style>
Share:

Wednesday, January 5, 2022

How to create copy to clipboard in Vuetify VujeJs application

This is a quick tutorial on how we can add copy to clipboard functionality in the VueJs application.

In this example, we are going to create the invitation code where users can copy that code in the clipboard so that they can share it simply by copy-paste.

Let's create a simple component called CopyToClipBoard.vue and add a template

<template>
    <div>
        <v-card height="460" class="mt-8">
            <v-card-title class="justify-center mb-2 pb-0">
                <span class="text-center red--text">Your invite code</span>
            </v-card-title>
            <v-card-text class="text-center mb-0 pb-0">
                <v-chip color="grey" text-color="white" class="font-weight-bold">
                    <span class="inv-text">A0xU76E</span>
                    <v-divider
                            class="mx-4"
                            vertical
                            light
                    ></v-divider>
                    <v-tooltip top>
                        <template v-slot:activator="{ on, attrs }">
                  <span @click="copyCode" @mouseout="reset" style="cursor: pointer;" v-bind="attrs"
                        v-on="on">Copy</span>
                        </template>
                        <span>{{copyText}}</span>
                    </v-tooltip>
                </v-chip>
            </v-card-text>
        </v-card>
    </div>
</template>
Here, we are using vuetify UI framework, you can use your own HTML CSS. We are adding two events called @click for copy text to clipboard and @mouseout event for resetting the default value. 

Let's add the data:
created() {
    this.copyText = this.text
  },
data () {
    return {
      invitationCode:"A0xU76EJK",
      text: "Copy to invite",
      copyText: ''
    }
  },
Create the methods used in template:
methods : {
    async copyCode() {
      await navigator.clipboard.writeText(this.invitationCode);
      this.copyText = "Copied"
    },
    reset() {
      this.copyText = this.text
    }
  }
}
We are using vuetify tooltip to give the copy information. 

When the user clicks on the button it will call copyCode function and will copy in clipboard. In order to do so, we are using navigator.clipboard API which allows user to grant the website or app permission to access the clipboard. 

After that, we have to copy the invitationCode value so we pass this value as a parameter.

The sample demo looks like below:



The overall implementation looks as:
<template>
    <div>
        <v-card height="460" class="mt-8">
            <v-card-title class="justify-center mb-2 pb-0">
                <span class="text-center red--text">Your invite code</span>
            </v-card-title>
            <v-card-text class="text-center mb-0 pb-0">
                <v-chip color="grey" text-color="white" class="font-weight-bold">
                    <span class="inv-text">A0xU76E</span>
                    <v-divider
                            class="mx-4"
                            vertical
                            light
                    ></v-divider>
                    <v-tooltip top>
                        <template v-slot:activator="{ on, attrs }">
                  <span @click="copyCode" @mouseout="reset" style="cursor: pointer;" v-bind="attrs"
                        v-on="on">Copy</span>
                        </template>
                        <span>{{copyText}}</span>
                    </v-tooltip>
                </v-chip>
            </v-card-text>
        </v-card>
    </div>
</template>

<script>
    export default {
        name: "CopyToClipBoard",
        data () {
            return {
                invitationCode:"A0xU76EJK",
                text: "Copy to invite",
                copyText: ''
            }
        },
        created() {
            this.copyText = this.text
        },
        methods : {
            async copyCode() {
                await navigator.clipboard.writeText(this.invitationCode);
                this.copyText = "Copied"
            },
            reset() {
                this.copyText = this.text
            }
        }
    }
</script>

<style scoped>
    .inv-text {
        min-width: 150px;
        font-size: 20px;
    }
</style>
Share:

Tuesday, January 4, 2022

How to install icon fonts in vuetify vue application

This is a quick tutorial on how we can install icon fonts for material icons and font awesome

Although vuetify uses material design icons, that might not be sufficient all the time so we need to use some other library for it.

We can simply install a font by including the specified icon library CDN. For this, go to the project directory and inside it, you can see the index.html file under the public folder.  


Here, add the material icons and font awesome icon CDN link as below.

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.x/css/font-awesome.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css">
After adding this, we can simply use icons for e.g: 

From font awesome, simply use the fa- prefixed on icon name:
<v-icon left color="blue" size="50">fa-twitter</v-icon>
For google fonts, go to the google font and click the icon, we can see the icon font name similar as below, simply use the name.
<v-icon left color="blue" size="50">logout</v-icon>
Share:

How to implement social media share buttons in Vue.js

In this tutorial, we are going to implement the social media share button using Vue.js.

Here, we are using the dependency called vue-socials which is very handy while implementing social media share buttons. It contains almost all the social share button functionality that we need and is lightweight and highly customizable.

In this tutorial, we are going to implement the Facebook and Twitter share button as an example. 


Install Dependency:

Go to your project directory and install the dependency.

If you are using the npm package manager

For Vue 2: 
npm install vue-socials
For Vue 3:
npm install vue-socials@next

If you are using the yarn package manager
# Vue 2
yarn add vue-socials

# Vue 3
yarn add vue-socials@next

Now, it's time to import the required share button components. Here we are creating the SocialMediaShare.vue component for demo. 

Inside this component, we are going to import the Facebook and Twitter share button component as below:
import { SFacebook, STwitter } from 'vue-socials'
Now, we need to register the components
  components: { SFacebook, STwitter }
After component registration, let us use it into the template
<div >
    <s-facebook
            :window-features="windowFeatures"
            :share-options="facebookShareOptions"
            :use-native-behavior="useNativeBehavior"
            @popup-close="onClose"
            @popup-open="onOpen"
            @popup-block="onBlock"
            @popup-focus="onFocus"
            style="text-decoration:none"
    >
        <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                aria-hidden="true"
                focusable="false"
        >
            <path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
        </svg>
    </s-facebook>
    <s-twitter
            :window-features="windowFeatures"
            :share-options="twitterShareOptions"
            :use-native-behavior="useNativeBehavior"
            @popup-close="onClose"
            @popup-open="onOpen"
            @popup-block="onBlock"
            @popup-focus="onFocus"
            style="text-decoration:none"
    >
        <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                aria-hidden="true"
                focusable="false"
        >
            <path
                    d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"
            />
        </svg>
    </s-twitter>
</div>
We are using some random SVG for icons, we can use the images or custom icons. 




Let's create the data and methods:
data () {
    return {
      windowFeatures: {},
      facebookShareOptions: {
        url: 'https://github.com/',
        quote: 'Quote',
        hashtag: '#Github',
      },
      twitterShareOptions: {
        url: 'https://github.com/',
        text: 'Hello world',
        hashtags: ['hash', 'tag'],
        via: 'twitterdev',
      },
      useNativeBehavior: false,
    }
  },
  methods:{
    onClose() {},
    onOpen() {},
    onBlock() {},
    onFocus() {},
  }

If we run the application we can see something like this:


Click on icons, we can share the content on those social media. We can change the content from data in component. 

For now, we are using the Github link and dummy text as examples.

If we want to import all the share buttons available then import all components as below inside main.js file.
 // Vue 2
import Vue from 'vue'
import VueSocials from 'vue-socials';

Vue.use(VueSocials)

// Vue 3

import { createApp } from 'vue'
import VueSocials from 'vue-socials';
import App from './App.vue'

const app = createApp(App)
app.use(VueSocials)
The overall implementation of the above example looks as below:
<template>
    <div >
        <s-facebook
                :window-features="windowFeatures"
                :share-options="facebookShareOptions"
                :use-native-behavior="useNativeBehavior"
                @popup-close="onClose"
                @popup-open="onOpen"
                @popup-block="onBlock"
                @popup-focus="onFocus"
                style="text-decoration:none"
        >
            <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="24"
                    height="24"
                    viewBox="0 0 24 24"
                    aria-hidden="true"
                    focusable="false"
            >
                <path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
            </svg>
        </s-facebook>
        <s-twitter
                :window-features="windowFeatures"
                :share-options="twitterShareOptions"
                :use-native-behavior="useNativeBehavior"
                @popup-close="onClose"
                @popup-open="onOpen"
                @popup-block="onBlock"
                @popup-focus="onFocus"
                style="text-decoration:none"
        >
            <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="24"
                    height="24"
                    viewBox="0 0 24 24"
                    aria-hidden="true"
                    focusable="false"
            >
                <path
                        d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"
                />
            </svg>
        </s-twitter>
    </div>
</template>

<script>
    import { SFacebook, STwitter } from 'vue-socials'

    export default {
        name: "SocialMediaShare",
        components: { SFacebook, STwitter },
        data () {
            return {
                windowFeatures: {},
                facebookShareOptions: {
                    url: 'https://github.com/',
                    quote: 'Quote',
                    hashtag: '#Github',
                },
                twitterShareOptions: {
                    url: 'https://github.com/',
                    text: 'Hello world',
                    hashtags: ['hash', 'tag'],
                    via: 'twitterdev',
                },
                useNativeBehavior: false,
            }
        },
        methods:{
            onClose() {},
            onOpen() {},
            onBlock() {},
            onFocus() {},
        }
    }
</script>
Check out for other share button lists, usage, and demo from these links.

Share:

Friday, January 1, 2021

Adding PWA support in existing VueJs application

In this tutorial, we are going to add the PWA support in the existing VueJs application.

1. Install Vue CLI

npm install -g @vue/cli
# OR
yarn global add @vue/cli

2. Add PWA in our application

Let's open the terminal or command prompt and go to the project directory and add PWA  to the project.
vue add pwa
This will add a couple of files and settings for PWA in our existing application.

1. registerServiceWorker.js under ./src directory.



/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {
      console.log('Service worker has been registered.')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}
Inside this file, the service worker is registered, and also, we can see the different hooks implemented which we can use in different cases like when the update is found in the app when the user is offline etc.

2. Dependencies added

Under package.json you can see the register-service-worker and PWA plugin is added.


3. Added some icons

Under public/img/icons/ folder some icons are added for mobile, desktop display. Make sure to change your icons for different devices. For more detail on changing this follow the following article.


If you want to configure via config file follow this guide.

Besides this, registerServiceWorker is imported inside main.js file.

3. Build and Deploy the application.

Build and deploy the application, you can see the service worker is activated and running.


You can see the cached file inside cache storage.

By default, it uses default mode which means a service worker is generated for us. If you want to customize it follow the following articles.


To notify the users about the app update follow the following post.


Share:

Sunday, December 20, 2020

VueJs PWA: Notify User about the App Update | skipWaiting

Once the application is updated and deployed then, the new version of the application will be available. But how we can notify the user that a newer version is available while they are interacting with the application. How to give the user control over app updates.

Please check out my previous articles on PWA:


1. Understanding how the UI get an update when new content is available:

When you change the app content and deploy it then, you can see in the browser what the service worker is trying to do.




Here, you can see, as soon as the new content is available new service worker trying to install it and is in waiting state.

Although, the old service worker is registered and serving with the old content. The new service worker will be still in a skip waiting state i.e waiting.

Here, once we notify the user about the new update and if they allow us to update the app we can simply do skip waiting and reload the page for new content. After that, a new service worker will be activated and will serve with a new update available.

2. Register the custom event to notify the user about the app update:

We know that service worker can't access the web DOM element directly. As they will run in the background in a separate thread. So we have to notify users from our application. In order to do so, we need to register the custom event which can be listened to in the application.

You can see the file registerServiceWorker.js which is generated by Vue CLI.

/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {
      console.log('Service worker has been registered.')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}

There are multiple events that will be triggered. Here, we need to use the updated hook to notify the user. Let's register for the custom event.
updated (registration) {
      console.log('New content is available; please refresh.')
      document.dispatchEvent(
          new CustomEvent('serviceWorkerUpdateEvent', { detail: registration })
      );
    },
Now let's add this event listener serviceWorkerUpdateEvent in our application. Inside App.vue
created() {
    document.addEventListener(
        'serviceWorkerUpdateEvent', this.appUpdateUI, { once: true }
    );
  },





Let's add some data used and appUpdateUI function.
data: () => ({
    registration:null,
    isRefresh: false,
    refreshing: false,
  }),
  methods:{
    appUpdateUI:function (e){
      this.registration = e.detail;
      this.isRefresh = true;
    }
  }

When the updated event inside registerServiceWorker.js triggered then serviceWorkerUpdateEvent will be triggered which calls the appUpdateUI to show the button to update. Let's add a simple button inside the template as a user interface to update the app. You can use a nicer snack bar instead.
<button v-if="isRefresh" @click="update">Update</button>
Let's add update() inside methods.
update(){
     this.isRefresh = false;
     if (this.registration || this.registration.waiting) {
       this.registration.waiting.postMessage({type:'SKIP_WAITING'});
     }
   },
Now when the user clicks the update button then it will send the post message of type 'SKIP_WAITING' to communicate with the service worker.

If you are using GenerateSW mode then make sure this post message matches the message listener inside the service worker. You can verify it by building your app. Once the app is built then under dist/ folder you can find the service-worker.js to verify.

If you are using injectManifest mode then, use the message listener as below inside service-worker.js:
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});
Now, this listener will be triggered and it will do skip waiting. The last thing is we need to reload the application to reflect the content change.



For this, we can use 'controllerchange' listener in our application. Under App.vue inside created use the following listener.
created() {
    navigator.serviceWorker.addEventListener(
        'controllerchange', () => {
          if (this.refreshing) return;
          this.refreshing = true;
          window.location.reload();
        }
    );
  },
This is the idea to notify the user of the App update.
Share:

VueJs: How to Get the App Version from package.json

This is a quick tutorial on how we can access the app version.

While building applications, there may be a different phase of development. We need to have a clear vision that which version of the application is on the server.

In the VueJs application under package.json file, you can see the one property called version. We can use this version while deploying to indicate the different versions of the application.


So, what we can do is simply increase the value for a different version of development.

The version can be accessed in our application by simply importing this file as below:

import {version} from '../../package'
Make sure it's accessible. Here, e.g '../../' will give the access for the package which is used under /src/somefolder/component.vue. As the package.json file is under the app root directory. If you want it inside App.vue you can use '../' instead.
data: () => ({
    appVersion:version
  }),
Now access in your template or can set in the store and access it.

<h1>{{appVersion}}</h1>

If you want the package version inside npm script:

const version = process.env.npm_package_version
Share:

How to Use and Customize Service Worker in VueJs Progressive Web Apps(PWA)

 1. Introduction:

What exactly a service worker? What is the need of service worker in our web application?

The service worker is the script that runs in the browser in the background. This means the service worker will run in a separate thread and is independent of our web pages. Service worker can't access the DOM directly.

The service worker is very handy for the caching strategy, push notification, background sync. This means we can manage which files need to be cache and which are not.

Also particularly for mobile app, when it is not opened and needs to send the push notification As well as if the app is not opened and needs to send the request to the server.

Please visit our previous articles on PWA:


2. Default Implementation of Service Worker in VueJs PWA:

VueJs application with Vue CLI uses the default configuration to set up and use the service worker.



If you build your application then, you can see the service worker file generated.
yarn build
 

There are two webpack plugin mode, one is GenerateSW mode which will generate the complete service worker. Vue CLI uses this as a default mode.

Another is InjectManifest mode, which allows us to customize and organize as our requirement and we do have full control over service worker.

If you want to know when to use and when not to use these modes please visit Workbox webpack Plugins

You can see the default service worker generated after building the application as shown in the figure above.

We are going to use the InjectManifest mode so that we can have control over the service worker.

3. Register the Service Worker:

The service worker registration is done by Vue CLI by default. You can see the registerServiceWorker.js under /src folder, the file looks as below:
/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {
      console.log('Service worker has been registered.')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}
Note: make sure to change the service worker name if you use a different name for it.





Here, the service worker is enabled only for production, enabling service worker in development mode is not encouraged, as it will not reflect the current changes in development, instead it will use cached resources. All the events will be triggered in different cases. 

4. Customize Service Worker with InjectManifest Mode:


Let's copy the service worker service-worker.js file from the dist/ folder or create a new  service-worker.js file under the src/ directory.


Now, let's configure the config to notice that we are using the InjectManifiest mode and provide the newly created service worker path to use that service worker.

For this, create a vue.config.js file under the app root directory. Make sure to have the same name mentioned so this config file will be used by Vue CLI. The file looks as below.


Now, lets set up the config:
 pwa:{
        workboxPluginMode: "InjectManifest",
        workboxOptions:{
            swSrc:"./src/service-worker.js",
        }
    }



Add the above PWA configuration inside the vue.config.js file. Here, we are using plugin mode as InjectManifest and give the path of the newly created service-worker.js file.

The custom service worker file needs to be as shown below:

workbox.core.setCacheNameDetails({prefix: "vue-pwa"});

self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

self.addEventListener('message', (event) => {
    if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting();
    }
});

Let's change the cache name from "vue-pwa" to "vue-pwa-test" and build the application. If you look into the service-worker.js under the dist/ folder and if you see the changes there, you are good to go.

Also, you can see some import scripts added at the beginning of the file by Vue CLI which looks something like below.
importScripts("/precache-manifest.7b241a43a2278739512d45eb32884cc1.js", "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
The precache-manifest has a different json config for different files to cache. Note, the file name to be cache will be different in each build. Now, build and deploy the application.

Note: each change in the application will be reflected in the browser after new content is updated and the app is reloaded or refreshed.



Now, click on "skipWaiting" and reload the page which will reload our application with new changes. We will do this skipWaiting from the application in the next tutorial by giving the user control of the app update. Or if you do it right away especially for testing you can add the following inside service-worker.js.
workbox.core.skipWaiting();

You can see the caching files under the cache storage tab.



The life cycle of the service worker is implemented by default. You can handle each event/hooks inside registerServiceWorker.js file as mentioned in step 3.

Now, you can especially handle different push notifications, background sync, using indexdb inside this custom service worker created.

5. Service Worker Life Cycle Event:

If you want to implement the lifecycle event on your own you can use them inside the service-worker.js file itself. Make sure to unregister the service worker from the registerServiceWorker.js file and register your service worker. It can be done in the main.js file.  Some of the life cycle events are below: 
self.addEventListener('install', (event) => {
  console.log("Installing ....................");
});
self.addEventListener('activate', (event) => {
  console.log("activateing ....................");
});
self.addEventListener('fetch', (event) => {
  console.log("fetching ....................");
});
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});
If you want to know more about these events please look Service Workers: an Introduction.

Share:

Wednesday, December 16, 2020

VueJs Progressive Web Apps(PWA): How to Change the App Name, Icon, Color, Display for Mobile Devices.

In this tutorial, I will show you how to create and change the Manifest file. The manifest file will allow the way of displaying our application, especially on mobile devices i.e showing app name, app icon for different size mobile screen, the color of the app, etc.

Please visit our previous articles on PWA:

Create a Simple VueJs Progressive Web Apps (PWA) and Deploy to Firebase


Create a Manifest file.

The default manifest file will be created when you build your application with Vue CLI. Let's build our application.

yarn build
Now you can see the manifest.json file under the dist/ folder. This is the file that we are going to modified according to our requirements.



To change this file first copy the file inside the public/ folder. On each build, all the files under the public folder will be copied to the dist/ folder so we have our changes in production.


 The manifest.json file looks like below:
{
  "name": "vue-pwa",
  "short_name": "vue-pwa",
  "theme_color": "#4DBA87",
  "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"
    },
    {
      "src": "./img/icons/android-chrome-maskable-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "./img/icons/android-chrome-maskable-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "background_color": "#000000"
}

We will discuss each property used here. If you have difficulties generating this file make sure to create one with this structure.

If you deploy with this default configuration and open it into your mobile then you can see the below display.

Note: we are using the default vue CLI application for testing.


name :

This will be the name displayed on the screen(splash screen) before the application load the CSS. Please change the name you want for your application. When you click the icon then you will see this name and icon as a first screen.

short_name:

This is similar to the name property but displayed under the launcher icon as shown above.

theme_color:

The default theme color of the application.

icons:

Different icons used for different screen mobile devices. For e.g the different launcher icon size for the different screen for the android device looks as below:


Make sure to put different size image icon for your app under public/img/icons folders or if you want to use in a different folder inside public/ then use the same path on manifest.json file.

By providing different size icons, the icon will be used according to the different screen size devices.

start_url:

This will be the URL for the entry point when you add the app to the home screen.

display:

"that determines the developers’ preferred display mode for the website. The display mode changes how much of browser UI is shown to the user and can range from the browser (when the full browser window is shown) to fullscreen (when the app is full-screened)."

background_color:

This defines the background color of the splash screen before the application CSS is loaded. When you click the app on your device, initially it will load the background color with icons before the app is loaded.

For other properties and more descriptions please visit Web App Manifest. 

Finally, make changes to the properties under manifest.json and build the application and deploy. You can see the desired changes in your mobile devices.



Share:

Monday, December 14, 2020

How to Test Our VueJs Progressive Web Apps(PWA) Locally over HTTPs.

In this tutorial, I will show you how we can test our PWA application locally. The PWA needs an HTTPS connection to work properly. So, it's better to test the application over HTTPs locally.

Make sure you have a sample running PWA locally. I am using vuejs sample PWA application for testing purposes.

1. Build our application:


yarn build
This will create the dist folder which is deployment-ready.



2. Install an http-server package:

First, install http-server package globally, which helps to run the dist folder. For this, open a terminal or command prompt to run the following command.

For npm package manager:
npm install http-server -g

For yarn package manager:
yarn global add http-server

Make sure to refresh your terminal or command prompt after installing the package.

Now, run the application using this package.
http-server dist/
Where dist/ is the folder created while building the application. This will run the application. If you open the application, you will see that our application is not working properly as no service worker is registered.



3. Install and setup Ngrok to run the application.

Here, we are using the third-party service called Ngrok which is free for testing.

What it will do is it will simply tunnel our local server with a specific port over HTTPS which is what we want to test locally. 

Download it from Ngrok download.

Go to the downloaded folder and extract it. You can see the executable binary file. In order to run the file please follow as below.

For Windows:

Simply double click that .exe file. Which will open in the command prompt.

Now, you are ready to tunnel your local server. Use the following command to tunnel your server.
ngrok.exe http 8080
Make sure your application is running in port 8080 otherwise, use your own port instead.


You can see similar to the above. Now you can open the HTTPS tunneled URL.

If you are getting an Invalid Host header issue then you can simply run the below command instead which resolves the issue.
ngrok.exe http 8080 -host-header="localhost:8080"
For Linux: Go to the extracted Ngrok file directory and use the following command.
./ngrok http 8080




If you get the issue with an Invalid Host header then use the following command instead:
./ngrok http 8080 -host-header="localhost:8080"
Once, you open the URL, you can see the service worker for PWA will be working as below.





Share:

Sunday, December 13, 2020

How to Deploy VueJs Application to Firebase for Different Environment

In this tutorial, we are going to deploy our Vue application to the firebase server for different environments.

Before putting any project into production it needs to develop, QA first.

So, for different cases, we may need different configurations and need to use different server resources.

According to this requirement, we need to set up different configuration files for different environments. So while deploying, it can take a specific config for the corresponding environment.

Generally, what we are going to do is:

  1. Create different projects for different env in firebase
  2. Set up firebase hosting in our application
  3. Configuring test config file for different environment
  4. Deploy the application for different environment

1. Create projects in firebase for different environment

Go to the "https://console.firebase.google.com/" and create a project.

Here we are creating two sample projects for develop and qa environment.

- Give the name of the project, we are giving "develop-vue-test" to develop and "qa-vue-test" to qa environment








Note: Create two different projects for two different environments.

2. Set up a firebase hosting in our application.

Here, we are considering you already have your vuejs application. Go to the project directory and initialize the firebase.

- Install Firebase CLI:

For npm package manager:
npm install -g firebase-tools
For yarn package manager:
yarn global add firebase-tools

- Initialize your project:

firebase login
This will redirect you to login with a Google account. Use the same account to login which is used to create for the different firebase projects previously.


Now, initialize the firebase project using the following command:

firebase init




The above process will create the following two different files in your project directory:

- .firebaserc:

{
  "projects": {
    "default": "develop-vue-test"
  }
}
As we use default firebase project as "develop-vue-test" while doing firebase init.

- firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}
This is the firebase config file where you can see the setup we did previously. For e.g "public": "dist" as we choose dist as public.

3. Configuring test config file for the different environment:

Now let's create some config files in the project directory for different env.

For production:

.env.production

For develop:

.env.develop
VUE_APP_ENDPOINT=https://develop.com
You can create whatever config key-value pair here with the respective environment. We are using VUE_APP_ENDPOINT test sample.

For qa:

.env.qa
VUE_APP_ENDPOINT=https://qa.com
You can access that config file property anywhere by using:
process.env.VUE_APP_ENDPOINT



Now let's add a qa-vue-test firebase project inside firebase.json
{
  "projects": {
    "default": "develop-vue-test",
    "qa": "qa-vue-test"
  }
}
Let's go to the package.json file and add and change the build script to use this config file.

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "develop": "vue-cli-service build --mode develop",
    "qa": "vue-cli-service build --mode qa"
  },
Here, we added two more scripts for develop and qa environment.

"develop": "vue-cli-service build --mode develop",
"qa": "vue-cli-service build --mode qa"

4. Deploy the application:

For develop:
yarn develop
Which will build the application for develop env.
firebase deploy


as inside the firebase.json file, the default project is selected as develop-vue-test so it will simply deploy to develop.


For qa:
yarn qa
firebase deploy -P qa
Make sure the name "qa" needs to same as the name of the project defined in firebase.json. This will simply deploy the build folder to "qa-vue-test" firebase project.

Finally, we have successfully deployed our vuejs application to firebase for different environments.

If you want to track the hosting inside the firebase console then you can go to the Hosting tab in the console.




Share:

Saturday, December 12, 2020

Create a Simple VueJs Progressive Web Apps (PWA) and Deploy to Firebase

In this tutorial, we are going to create a simple VueJs PWA application and also show you how to deploy it to firebase. As we know that PWA is being more famous these days due to its very fast performance and can be used for different platforms with a single code base as well as the offline functionality and caching support.

1. Install Vue CLI

If you haven't installed the Vue CLI, open the command prompt or terminal and run the following command to install it globally. 

- For npm package manager:

npm install -g @vue/cli
- For yarn package manager:

yarn global add @vue/cli



2. create a VueJs PWA project:

vue create vue-pwa
Now, select the manual option

Select Progressive Web App (PWA) Support option from the list. As you need to go to that option using the down arrow on the keyboard and hit the spacebar to select that option. Also select the other option if you are going to use them like Router, Vuex, etc.



Now, go to the project directory and run the application.
cd vue-pwa
yarn serve
Vue CLI created a sample demo application for us so, we are using the same for this tutorial. If you look into the Application tab by doing the inspect element of the above running project, there you can see the Service Workers. The main heart of the PWA is this service worker. As if we run the PWA application locally the service worker will not work, as it required an HTTPS secure connection.

 

The service worker is the script that will run in the background separately from the application which helps to install, activate, caching of our application. There are more thing about service worker, will discuss in the future article.

So how we can test the PWA application. As we can use some third-party services as well as we can simply deploy to firebase.

3. How to test our PWA application locally:

- Build the application in production mode:

yarn build
This will create the deployment-ready dist folder.

First, run this locally using http-server package. In order to do the show first install it globally.
npm install http-server -g
Now, run the dist folder:
http-server dist/
Which will run the application. Now what we need to do is tunnel our local server with HTTPS. Please follow this Tunnel local server to the public internet with HTTPS using Ngrok. This will tunnel our local server over HTTPS. Now open the tunneled URL. You can see the service worker as follows.



Also, you can see the + icon to install your PWA app in the browser.


If you run the same tunneled URL on the mobile then you will get the following screen to install your PWA application.

Add vue-pwa to Home screen if you click this, it will add the application to the home screen so that you can later open it by simply clicking it.

4. Deploy to firebase.

Now, let's deploy the build dist folder in the firebase server.

- Go to the firebase console "https://console.firebase.google.com/"

- Create a project by giving the project name.

- Installing firebase in our system.

 Open the command prompt or terminal and install firebase globally.
npm install -g firebase-tools
Initialize the project: Make sure to go to the project directory.
firebase login
This will ask for a google login. You can authenticate the google account where your firebase console project is created. If you want to logout use the following command.
firebase logout
Now, initialize the project:
firebase init
This will ask a couple of question make sure you insert the right as below:
We are simply using it for hosting our application so chose the same option.


Make sure the above setting. The public directory will be dist in our case, as we are deploying the dist folder.

This will create two files in our project:

- .firebaserc

where you can find the project's configuration. Make sure you have the same project name in the "default" section to that create on the firebase console. While deploying it, will use the same firebase console project created. In my case, it is "vue-pwa-7ed80". The config file looks like below.

{
  "projects": {
    "default": "vue-pwa-7ed80"
  }
}

- firebase.json

where all the hosting configuration is done. The config file looks like below.

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Deploy our application.

First, build the application:
yarn build

Now, deploy the build dist folder

 
firebase deploy

This will deploy our application to the firebase server. You can see the deployment history and track from the console under the Hosting section inside the firebase console.

Firebase gives the live HTTPS URL which you can see in the firebase console. If you run that URL you will see the service worker will register and can be run the application as a PWA application.

Finally, we created a simple VueJs application with PWA support and successfully deployed it to the firebase.



Share: