Currently, I am working on a college assignment, and I was asked to use PWA for this task. At first, I was hesitant, but I decided to give it a try. After all, learning something new is a fun activity. So now I want to share what I have learned while exploring PWA.
1. Creating PWA with Vue JS
The steps to create a new PWA project with VueJS are quite easy. For those who haven’t installed vue-cli, you can run the following command in your favorite console.
npm install -g vue-cli
After that, to create a new project, continue by running the following command:
vue init pwa pwa-github-api
After running the command above, several questions will appear in the console for initializing your project.
Then run the command as provided by your console:
cd pwa-github-api
npm install
npm run dev
If all dependencies have been downloaded and are running, try accessing http://localhost:8080 to open the application. The first appearance of the application will look like the image below.
2. Creating a Service
To use the Github API, in this tutorial, I will use Axios , which is a JavaScript library that handles HTTP requests. To use Axios, first, add Axios to the project you created earlier.
npm install -s axios
Then, in the /src folder, add a /services folder to store files related to the service. Next, add the Api.js file as the base for each of our services.
import axios from 'axios'
export default() => {
return axios.create({
baseURL: 'https://api.github.com/'
})
}
Then, in the same folder, also add the GithubService.js file, which will register the Github endpoints we will use.
import Api from '@/services/Api'
export default {
searchUser (params) {
return Api().get('users/' + params.username);
},
}
In GithubService.js, there is one function called searchUser that we will call later from the component. The searchUser function will accept one parameter, which is an object that will hold the Github username we want to search for.
3. Creating a Search Page and Displaying Search Results
For the display, I will use the built-in component that already exists, but I will rename the Hello.vue component to Home.vue. Changing the name is optional, but it is better to use a name that fits each class. If you also change the name of the file, don’t forget to update the index.js file in the /router folder. Here is my index.js file after renaming the Hello.vue component to Home.vue.
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
}
]
})
Then, in Home.vue, I created an input field to enter the Github username to be searched. There is also a search button that will trigger the API call process. Here is my Home.vue file.
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<input type="text" name="username" v-model="username"/> <br>
<button @click="getUserData"> Search </button>
<div v-if="user !== null" class="profile">
<img v-bind:src="user.avatar_url" width="200" height="200"> <br>
<label>Username : {{ user.login }}</label> <br>
<label>Profile name : {{ user.name }}</label> <br>
<label>Profile bio : {{ user.bio }}</label>
</div>
</div>
</template>
<script>
import GithubService from '@/services/GithubService'
export default {
name: 'hello',
data () {
return {
msg: 'VueJS PWA consuming Github API',
username: '',
user: null
}
},
methods: {
async getUserData() {
this.user = null;
const result = await GithubService.searchUser({
username: this.username
}).then(response => {
this.user = response.data
}).catch(error => {
console.log(error)
})
if(this.user !== null) {
console.log(this.user);
}
}
}
}
</script>
<style scoped>
h1, h2 {
font-weight: normal;
}
input {
width: 40%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
.profile {
padding: 16px;
}
label {
font-size: 20px;
}
</style>
Here is the home display.
In my Home.vue component, I created a function called searchUserData. In this function, we will call the API using the service we created earlier. In the searchUserData function, I used Async/Await, which simplifies the code and allows for asynchronous function calls. The await keyword will pause the function until it receives a return value in the form of a promise. If you are not familiar with the asynchronous concept in JavaScript, you can read
this article
by
Sastra Panca Nababan
, which I find easy to understand.
Then the data returned from the API call will be displayed on our page. The data returned from the API is in JSON format. Here is an example of the return.
{
"login": "ecojuntak",
"id": 9149602,
"avatar_url": "https://avatars1.githubusercontent.com/u/9149602?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/ecojuntak",
"html_url": "https://github.com/ecojuntak",
"followers_url": "https://api.github.com/users/ecojuntak/followers",
"following_url": "https://api.github.com/users/ecojuntak/following{/other_user}",
"gists_url": "https://api.github.com/users/ecojuntak/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ecojuntak/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ecojuntak/subscriptions",
"organizations_url": "https://api.github.com/users/ecojuntak/orgs",
"repos_url": "https://api.github.com/users/ecojuntak/repos",
"events_url": "https://api.github.com/users/ecojuntak/events{/privacy}",
"received_events_url": "https://api.github.com/users/ecojuntak/received_events",
"type": "User",
"site_admin": false,
"name": "Eko Simanjuntak",
"company": null,
"blog": "",
"location": null,
"email": null,
"hireable": null,
"bio": "always be newbie",
"public_repos": 1,
"public_gists": 4,
"followers": 0,
"following": 9,
"created_at": "2014-10-11T09:03:01Z",
"updated_at": "2018-02-12T06:23:48Z"
}
From the JSON data above, we can obtain a lot of information and are free to use it. However, to shorten this tutorial, I will only use **avatar_url, login, name,** and **bio**. This data will be displayed. Here are the results of our experiment so far.
4. Deploying to the Server
So far, everything is fine, but when it comes to PWA, it wouldn’t be a PWA if we don’t try it on mobile devices. Before we test it on a smartphone, we must first deploy our work. In this tutorial, I will use Heroku to deploy the PWA application.
I will use Github as my code source, so I need to create a new repository on Github. Before putting all our code into the repository, there are a few things we need to add to our project.
1. First, we need to generate code that is ready for production.
To generate the code, we can run the following command:
npm run build
When the command finishes running, the /dist folder will appear in our project. This folder will store all the code that will be used in production later. In the /dist folder, there are two important files: manifest.json and service-worker.js. The service-worker.js file is the file that will work to cache our files later. These files need to be cached so that the browser does not have to make repeated requests to the server too often, which is basic knowledge of PWA, namely caching the static files that form our application shell .
2. Second, we add a file called server.js at the root of the project.
This file will be executed first when the server is started. This file will also run the code in the /dist folder that has been generated earlier. Here is my server.js file.
Then I also added several dependencies to my package.json file. The dependencies I added are needed to run the server.js that I created earlier. In the package.json, I also changed the scripts section, specifically the start section. When the start script is executed, I will run the server.js that I created earlier. Here are the changes to my package.json.
{
"scripts": {
"dev": "node build/dev-server.js",
"start": "node server.js",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src"
},
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"express": "~4.9.8",
"serve-static": "^1.10.0"
}
}
After finishing the code, now put all the code into your repository.
The next task is to create our new application on Heroku. First, we log in to the Heroku dashboard. Then create a new application. Once the new application is finished, select the Deploy tab on the dashboard, and we will configure the code source that will be recognized by the Heroku App.
After finishing, at the bottom there is a Deploy Branch button. Click on that button to deploy our application. Then in the Settings tab, we will add an environment variable, namely NODE_ENV = production.
Then try to run your application through the URL provided by Heroku. Here is the display after we finish deploying.
Then I tried to access the URL from my smartphone, and the result was…
When the URL is accessed from a smartphone browser, a request will appear to add the application to the smartphone’s Home Menu. After selecting Add To Home Screen, the icon of our application will automatically appear on the smartphone screen.
That concludes my exploration of PWA. If there is anything unclear, feel free to ask. If there is anything wrong, please let me know so it can be corrected in the future. You can find the repository here and the deployed result here . I hope this is useful.
Cappy Hoding! 🖖🏾