{"componentChunkName":"component---src-templates-tag-js","path":"/tags/pwa/","result":{"data":{"site":{"siteMetadata":{"title":"LoginRadius Blog"}},"allMarkdownRemark":{"totalCount":3,"edges":[{"node":{"fields":{"slug":"/engineering/guest-post/how-to-build-a-progressive-web-app-with-react/"},"html":"<p>A Progressive Web App (PWA) is a more dynamic web application that can run as a standalone. It offers benefits such as: </p>\n<ul>\n<li>performance;</li>\n<li>the ability to work with or without an internet connection;</li>\n<li>platform-specific; and, </li>\n<li>installable.</li>\n</ul>\n<blockquote>\n<p>You can learn more about the <a href=\"https://www.loginradius.com/blog/engineering/progressive-app-vs-native-app/\">differences between native apps and PWAs here.</a></p>\n</blockquote>\n<p>In this article, you're going to learn how to build a PWA using React. As React is a popular web framework, this article starts by going over the setup, development process, and spinning it up to see how it looks. For this example, you'll create a simple Counter Page that simply adds or subtracts a number based on button controls.</p>\n<h2 id=\"create-a-react-app-with-the-progressive-web-app-template\" style=\"position:relative;\"><a href=\"#create-a-react-app-with-the-progressive-web-app-template\" aria-label=\"create a react app with the progressive web app template permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create a React App with the Progressive Web App Template</h2>\n<p>Before you can begin coding, you need to set up your project. Let's start by ensuring you can use React (if you're already familiar with coding in React, you can probably skip this section!). You need to use Node.js with any development using web frameworks such as Angular, React, or Vue -- especially if you wish to use libraries and packages to assist in developing your project. </p>\n<p>A popular utility in using such packages and libraries is the Node Package Manager, simply referred to as \"npm\". This utility allows you to install/uninstall packages, start your React application build using webpack, and many more other features. For your needs, you can take advantage of npm to create a React application with a PWA template, which allows you to code right away. Whenever you start building a React app, you can use templates offered by Facebook using the 'create-react-app' command with npm. </p>\n<p>Let's build the PWA starter app by running the following command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npx create-react-app name-of-our-PWA-app --template cra-template-pwa</span></span></code></pre>\n<p>The above command can be broken down as follows:</p>\n<ul>\n<li><strong>npx</strong>: Every npm command needs to start with npm (or essentially with whatever node package manager you have installed, but 'npx' is used here, which comes with npm version 5.2.0). This helps you run npm packages and <a href=\"https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager\">takes care of many features</a>.</li>\n<li><strong>create-react-app</strong>: This command initiates the popular Create React App utility that helps you build the starter react project.</li>\n<li><strong>name-of-our-PWA-app</strong>: This is a filler title of your application. Name the app to whatever you would like. Here, the default 'my-app' name is used)</li>\n<li><strong>--template</strong>: This is an argument. When you have an argument, you're essentially enabling an option in the same command. Here, you can specify a specific template for our starter react application.</li>\n<li><strong>cra-template-pwa</strong>: The name of the PWA template for your PWA react application.</li>\n</ul>\n<p>Hitting 'Enter' after this command should initiate the build of your starter PWA React application. You should see a stream of prompts in your command-line interface. It may take a few minutes, but if you can see this screen after the command, you have created the project.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 592px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.641891891891895%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABdUlEQVQoz6VSa0/CQBA8jICU8hI1ooDiBxEQebWUUh4VWkAQG///jxl3r2AaUgyJH+Z2+7i5udkRKd1G0V6jMF7i0dnizv7A7WSFwnQlnxmX5hxJbYJIow9R1yG4HkOsPUTWcpGxHKSNd6jaVG5WCVxT+hQqIUPfTiIUNQ2Jvo300JEbc4OZ3Mx95NWAeO5AVLt+3ZP9RcpLkklGLhRW1ZtA6Y0lWGGiO5Iq2Zqz5uAEhfSDQgpTRMqb9yRK1yeNty2q/vVDCQ+ffcKpJEzufOPriheN0PNR3VWyR4JJanq4BbwkDFteO07KWBEj1hr6oKHFOxaiLRPnbyYuOiNEqfL7cIV08g1FprL0cE/xYRTfN6i4XyjNNtSv8bTwZM9R4r48/8TDfCuHJxUHCfnEa4pNzpjJCedp2lcUoeyulwqCKgJ9aIxEQ4dKBPnxQsbkEEenWT8SH/ZJJek8FPbo13SJYH8iMqaDsuORh98ouR5E0/wXfgDK9lnyHdvUOwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cra-pwa.png\"\n        title=\"cra-pwa.png\"\n        src=\"/static/56f2c5d2b65cd178c1206a0e8d63a829/1b853/cra-pwa.png\"\n        srcset=\"/static/56f2c5d2b65cd178c1206a0e8d63a829/1b853/cra-pwa.png 592w\"\n        sizes=\"(max-width: 592px) 100vw, 592px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 388px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 110.30927835051547%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACFklEQVQ4y6WUX2/SYBjF3xYKtIU6Bkjihc6NiMg/LdACZdIV1rXMkQhzMNmM+i1k3hgT7zSZH2n3Gv1Exwc6Q8ySxZaLk7dp2l/OeXqesuyDe0h1isioj5DNpJDNppFObyKVTt6uVBIZejaXz2Ent42th/eRp2vGphcQX3+EMpsj/vYTlPefwZ1egE3mYNO5d96mkw+eJtcSvv+E9PUK7MsVuMvfYJe/wL79CC4xX8BdTYXUHULuDhAua2BbebCdAth2AEUqbShqH5IzgezOILQdsFIzuKJlA8n6EJJ9Aql3DLH/ElylBfakAVbU/CtSaWKz1YN8MCXgCLL9ak1gtUm12YPszKAcvkHEcMm6FhwYLumQ2wcI6/sIqaZ3s1D3ziBQjoDR9gCx50OE6+YKEtQhX2ogYZhIvHgHoWGBPVbXA4aKNaQ1g2Z4BtEcIVQzV5GDiKPuxDSbgNTD/jH4qkHu1pghX25Aae0ugVFjQJFrHijoLMOlFjI6rZ0zhWhdl7qo//uQH2iIHCaNhcNTxN0zJNxzKvcU/LPdldu/0P8B86U6NggY2xsj1j3yNsaiWT7tgKN5cuWmX4d1ctgh4GgJk/cXOz1e7rVkjRGh0vsC8kXqYcskGEW2JwRwPcCiOgv5jSyQQ6njej2kf+Ii6o0X/TgUVR13rEPEB+eI04cR9N7NYvuKXO0QxKaoDu2y5X3ZNVbvD+uGhwaPXliAAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-folder-structure.png\"\n        title=\"pwa-folder-structure.png\"\n        src=\"/static/33577ffd80429d8835275ec6105f302a/96c67/pwa-folder-structure.png\"\n        srcset=\"/static/33577ffd80429d8835275ec6105f302a/96c67/pwa-folder-structure.png 388w\"\n        sizes=\"(max-width: 388px) 100vw, 388px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Here, you can see the following folder structure of your application so far. There are a few files that you shall pay attention to when it comes to PWA's:</p>\n<ul>\n<li><strong><code>service-worker.js</code></strong>: This is a script that runs in the background once your application starts running. The service worker makes sure that you can use your React application offline and handle multiple requests for the UI. (<a href=\"https://developers.google.com/web/fundamentals/primers/service-workers?hl=en\">learn more here</a>)</li>\n<li><strong><code>manifest.json</code></strong>: This is basically a configuration file that lists different properties that you can customize specifically for progressive web applications. It can determine such things as icons, names, and colors to use when the application is displayed.</li>\n<li><strong><code>serviceWorkerRegistration.js</code></strong>: This file does the job of telling whether or not your service worker was successfully registered. If you look into the file, you'll notice multiple console logs that will be displayed depending on the status of the service worker once you deploy your application.</li>\n</ul>\n<h2 id=\"adding-a-simple-react-component\" style=\"position:relative;\"><a href=\"#adding-a-simple-react-component\" aria-label=\"adding a simple react component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Adding a Simple React Component</h2>\n<p>For your project, you'll build a simple Counter component, similar (if not exactly the same) to the example provided in the React docs: <a href=\"https://reactjs.org/docs/hooks-state.html\">Hooks State</a></p>\n<p>Let's start by creating a Counter component. Here, it is named as <code>Counter.jsx</code> and placed in a <code>components</code> folder.</p>\n<p>To speed things up, you can copy and paste the following code in your specific files. Here, it is built out as a simple page and some generic stylings for the component.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//Counter.jsx</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">React</span><span class=\"mtk1\">, { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;react&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;@mui/material/Button&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Counter</span><span class=\"mtk1\">(</span><span class=\"mtk12\">props</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">count</span><span class=\"mtk1\">, </span><span class=\"mtk12\">setCount</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">increment</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\"> + </span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">decrement</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\"> - </span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">style</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">{</span><span class=\"mtk12\">textAlign:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;center&#39;</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Counter App</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h3</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">variant</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;contained&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">increment</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">Button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">{</span><span class=\"mtk12\">count</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">variant</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;contained&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">decrement</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">-</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">Button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Counter</span><span class=\"mtk1\">;</span></span></code></pre>\n<p><strong>Note:</strong> Here, Material UI's Button component is used. You don't need to and can substitute the Button component with:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">increment</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>To use Material UI, run the following npm commands:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm install </span><span class=\"mtk12\">@mui</span><span class=\"mtk1\">/material</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm install </span><span class=\"mtk12\">@emotion</span><span class=\"mtk1\">/react </span><span class=\"mtk12\">@emotion</span><span class=\"mtk1\">/styled //these are additional dependencies </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> me to get Material UI working with the Counter component</span></span></code></pre>\n<h2 id=\"running-your-application\" style=\"position:relative;\"><a href=\"#running-your-application\" aria-label=\"running your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Running Your Application</h2>\n<p>In your command prompt, entering 'npm start' can spin up your application to a specific <code>http://localhost</code> url. You can start to see what work you've done so far.</p>\n<p>With these simple components, let's try to spin this application up and ensure it is working. </p>\n<p>Enter the command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm start</span></span></code></pre>\n<p>This starts the application at a set <code>http://localhost</code> URL. Once the dev server is working and live on the command prompt, go to the URL to view the application. You should see something similar to this:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 11.384615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAATElEQVQI12OYOXvu/9lz5/2fPGXa/96+Cf/7+lFxf//E/w0tnWDcP2EihnwfUM+ECZP+z5o95/+MGTP/M/wnApx+9OP/+Sc/iVH6HwAEuITcBlSqFgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"counter-base-app.png\"\n        title=\"counter-base-app.png\"\n        src=\"/static/088d475708c50e6be837f5ddf9ee3534/e5715/counter-base-app.png\"\n        srcset=\"/static/088d475708c50e6be837f5ddf9ee3534/a6d36/counter-base-app.png 650w,\n/static/088d475708c50e6be837f5ddf9ee3534/e5715/counter-base-app.png 768w,\n/static/088d475708c50e6be837f5ddf9ee3534/7ebf9/counter-base-app.png 1919w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Now, it's all good and ready to have the app live and working, but more interested in the PWA aspect.</p>\n<h2 id=\"running-your-progressive-web-application\" style=\"position:relative;\"><a href=\"#running-your-progressive-web-application\" aria-label=\"running your progressive web application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Running Your Progressive Web Application</h2>\n<p>Focus back on the <code>index.js</code> file. Make the following change:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// If you want your app to work offline and load faster, you can change</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// unregister() to register() below. Note this comes with some pitfalls.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Learn more about service workers: https://cra.link/PWA</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">serviceWorkerRegistration</span><span class=\"mtk1\">.</span><span class=\"mtk11\">register</span><span class=\"mtk1\">(); </span><span class=\"mtk3\">//change the service worker registration from &#39;unregistered&#39; to &#39;registered&#39;</span></span></code></pre>\n<p>Essentially, changing the service worker from unregistered to registered will allow you to utilize the app even when it's offline, a key benefit when it comes to PWAs. Check Google's explanation on this topic for more information: <a href=\"https://web.dev/articles/service-workers-registration\">Service Worker Registration</a></p>\n<p>With the PWA files setup, in order to view the difference, you can deploy your application to a static server using the <code>serve</code> package that will serve your application to localhost. In a nutshell, make sure you have the <code>serve</code> package by installing, building the application again, and using <code>serve</code> to deploy the application:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm install serve</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm run build</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">serve -s build //</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> you encounter an error with this command, </span><span class=\"mtk15\">try</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;npx serve -s build&#39;</span></span></code></pre>\n<p>Once you use the <code>serve</code> command, you should see the following message, having your application deployed to <code>http://localhost:5000</code>. It automatically adds the URL to your clipboard as well for quick pasting in your browser.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 359px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.038997214484674%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABtUlEQVQoz51S207bQBBdk0ICSri0qFBA4iYuSZ0Qr2MbX5JgyEUgEmgq2vKAkPj/fzicWTsqEby0D8dzPDsze2Zn1EZ7gI32EPv9MQ4Gd9jrjbCT3mDr4gbbAxubacz/ERZ1gorXxfH1BOVWF6ragvruv8fCWYRiM0aZwSUnwZLbxpJuY5G85GoUnYDnCebsAIX6uTkTq2rex1A13uTHUA6DmsQZoUMoN6JNaOOMt2hbUXYm3ItzX86DJFOobD9z6ghW2IEVs51GMNuGnYPcotJ3XJR5ScbNh8UUi6n0EmrYNyqtmiTkBU/dDPJuUy440cYnsUaU/UZhgc5vSR+7F9cMZuKxzhKYuB738Dm8wmqQkvex2Rlijf97vTFW6FNHDqwZha4MJkL4+IT0+QXV2wn0zz8GX6IrHHL6tdsHY+3RLzR/POJweI/6+De8hyd85SVmBvIEU4UWW1tgUYGsyLLfRYWQLSg0zs0mCJ/GfGqEmOO0S4ydb4TZwN4qnK+HqHC/ikySlZEgsbImUkgKCC+7HZRY3AzCvGmOmTf08/7rwf9BWp3WMDfp6O9O/Svc3DqhUf0KNFRAHuaCVJ0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-serve.png\"\n        title=\"pwa-serve.png\"\n        src=\"/static/c9a8359e93f7d5a8f4ddea4944617655/f5eb6/pwa-serve.png\"\n        srcset=\"/static/c9a8359e93f7d5a8f4ddea4944617655/f5eb6/pwa-serve.png 359w\"\n        sizes=\"(max-width: 359px) 100vw, 359px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>If you enter the <code>http://localhost</code> URL in your browser, you should see something similar to this:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 40.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEElEQVQoz5XQ7U6DMBQG4F6Djm2ok+8CAxmZsjjjvQDTaKAgC2HTZHeoN+FN+Pu1K9PM+AeaPOnpaXpOW1I3r9hs3pDlBeJkhSR9+CPl4jgV0vTx337Cz7DiBdW6xjNjIOgwPj6/8M51GaTe7sCqBnWzxZp3yTImFGWFnJXI+c1XT6193ObKdj7E2SHPigpEn93hRPVxNtEwUQzI5wpOB2Nu9EuSxsJx7thgKGMoX0IaXYAsogWoZUPVDAThNW6iJSzqwjApZ0M3aC8kmM1hWi4UzYR/FSKcR7yQIzapPeWNTCiq0Rm5Xd5j6gV8oYsCvufBs3VRSNMtMfdB9rcyLQe2G8D1Zvy5Dv8C2vupP74BqkMz+jHTrhwAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-service-worker.png\"\n        title=\"pwa-service-worker.png\"\n        src=\"/static/90d0aef82baba4315cab1a1b8ce921e5/e5715/pwa-service-worker.png\"\n        srcset=\"/static/90d0aef82baba4315cab1a1b8ce921e5/a6d36/pwa-service-worker.png 650w,\n/static/90d0aef82baba4315cab1a1b8ce921e5/e5715/pwa-service-worker.png 768w,\n/static/90d0aef82baba4315cab1a1b8ce921e5/29114/pwa-service-worker.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"pwa-features\" style=\"position:relative;\"><a href=\"#pwa-features\" aria-label=\"pwa features permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>PWA Features</h2>\n<p>With the PWA React application live, let's take a look under the hood and open up the Developer Tools (for Google Chrome, entering F12 opens the Dev Tools).</p>\n<p>After registering your service worker from <code>index.js</code>, you should be able to see it running in the Application tab. Inside that tab, on the left side you should see a Service Workers section. From here, you can see for <code>http://localhost:5000</code>. You have a Service Worker from your <code>service-worker.js</code> file and is activated/running.</p>\n<p>In the section above, you can see <code>Manifest</code> -- opening that should show you the relevant details you listed from your <code>manifest.json</code> files.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.61538461538461%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaklEQVQoz5WSvU7CUBiGewmCQEWkpS30FwopAamocfACpI2TYJwcHIyLJkYKRQaNUfSq0MEJd+EedH/tKWhioIIneXKSc773yXd+qEp1GwWjhHKlipq1j72aPYVt2bAse+YegeQah0eo1xugBoM39PvPGA5HCBov7x94HX1ikUH1Hp9w/9DDze0d3E4XTquNq6aDtnsN1+2i1e7g9LyJswsHLW/PCaDptPw8lc7IiNFxhMJRrCZYrCVTCEdohJfpnzkWpRH1IDVBLIUiWIknQJXKJohUlFSomo6cbkDR8pCV7C8kWYOQlmZC8hyf8bIFUHreAC+I/gIJkZlhebApYYoUlw6EZFQtB8rc2PJFvCD5XfJ/hBYSkg7TogLZk2aLJvTNXb9gXkeBQv84RJBkIZs7KB4cg2W4sXQingepTTIT4XeQ3KPoPQYvqmBZ7t9dkg4lWR0LfciCsQ7z5BKiUQHjfZ//HlmUFHwBERWGuHTl+YgAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-manifest.png\"\n        title=\"pwa-manifest.png\"\n        src=\"/static/72e264704e37dc7bb2a9dec4ad37ca4c/e5715/pwa-manifest.png\"\n        srcset=\"/static/72e264704e37dc7bb2a9dec4ad37ca4c/a6d36/pwa-manifest.png 650w,\n/static/72e264704e37dc7bb2a9dec4ad37ca4c/e5715/pwa-manifest.png 768w,\n/static/72e264704e37dc7bb2a9dec4ad37ca4c/29114/pwa-manifest.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>With your PWA app running using React, you've successfully built your first PWA React application! From here, you can test many PWA features, such as installation, offline viewing, and Lighthouse audit testing.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 39.07692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaElEQVQoz52MzUoCURiG5zq00XF0nD+jH3KcH0VoZbRQZ7KNURYE0S6XrYJWte8euo2kK4iypSuLWgQ6ajTj+HY8ipHhpg8e3u+8D99hjk9OsV87Qqns/KFIsG0HFcemWSw5KNsVFLa2IUoqkqIMSVZRsndwUDvEbrUKxvd9/DCc7R4BCNB6c3F738LrxwCj4bgDHh6fwIsqJGUFIZbHXaNBe8/zwGDBjEaT/PQCvLs+vvxgVrbbLzir13F5fYPziys8N5u0D4bB4g//O0y/38c8nW4HvV6P7AOaLqE3xXVdSrfbnSR9j93kltGNHHQji4xuQSOYZg6b+QI2NAtjp2VMSlozYRCXzeVhZfP0RssYM5/RJ55h2QhYNgouGkM0yiEel2FZe4hwIuk40vHUh8MsBEGix4mkTHwcoTDpl37DKEIcajKBtZSM1ZRCUJFSU9NdwbKiQCZeFnjIEunW04jxArhYguY833RDrR15xU/mAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-install.png\"\n        title=\"pwa-install.png\"\n        src=\"/static/3cb9b63c38ee39150c91b5e790a9997b/e5715/pwa-install.png\"\n        srcset=\"/static/3cb9b63c38ee39150c91b5e790a9997b/a6d36/pwa-install.png 650w,\n/static/3cb9b63c38ee39150c91b5e790a9997b/e5715/pwa-install.png 768w,\n/static/3cb9b63c38ee39150c91b5e790a9997b/29114/pwa-install.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>If you hit the '+' symbol on the right side of the URL ba,r you can install your PWA, just as done here.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 20.153846153846153%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAvklEQVQY022OS47CMBBEc40Rwk63HZO0fwOJCAo7dswh5v63KGyDsmLx1FJVdak68QmVSWIhNMbpfVNe4ZyHSMlIhjvJzuAmhPgLHzKkUP+r1iltcPygetvoyeJHGTwf/wjhjoPSu6f6d+5wJKSUsd42jKWsjlCa0Rk2kKHCOPsTluRxiYIlRyzXP8yXDXMcMRc9ed+y3jEcE2LMuK4b2LhWVod0RAa19Cuky6WC/Wh295gYdhjbOuIBuiyvhS8jyHS+MbNuyQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-lighthouse.png\"\n        title=\"pwa-lighthouse.png\"\n        src=\"/static/0540c7c3e60a931d7c2083aad390cb53/e5715/pwa-lighthouse.png\"\n        srcset=\"/static/0540c7c3e60a931d7c2083aad390cb53/a6d36/pwa-lighthouse.png 650w,\n/static/0540c7c3e60a931d7c2083aad390cb53/e5715/pwa-lighthouse.png 768w,\n/static/0540c7c3e60a931d7c2083aad390cb53/dd507/pwa-lighthouse.png 1528w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Use Workbox Lighthouse for testing the capabilities of your PWA: <a href=\"https://developer.chrome.com/docs/lighthouse/overview/\">Lighthouse</a></p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>You've learned about what PWAs are and how to build a PWA with React.</p>\n<p>If you want to quickly add user registration and authentication to your React PWA, you can <a href=\"https://www.loginradius.com/blog/engineering/user-authentication-react-application/\">use LoginRadius</a>. It eliminates the burden of building and maintaining user authentication from scratch and helps you focus entirely on building your app's core features.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"October 22, 2021","updated_date":null,"title":"How to Build a Progressive Web App (PWA) with React","tags":["React","PWA","npm"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/c7e3ca9131877e6d122821800050a259/ee604/blog-image.png","srcSet":"/static/c7e3ca9131877e6d122821800050a259/69585/blog-image.png 200w,\n/static/c7e3ca9131877e6d122821800050a259/497c6/blog-image.png 400w,\n/static/c7e3ca9131877e6d122821800050a259/ee604/blog-image.png 800w,\n/static/c7e3ca9131877e6d122821800050a259/f3583/blog-image.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Abdullah Pathan","github":"aonepathan","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/progressive-app-vs-native-app/"},"html":"<p>At the dawn of \"smartphones\" in late 2007, when Apple released the iPhone, there were native apps. Apple's app framework included a native app SDK that allows developers to take advantage of all the physical device features and topped it off with an app store that allows for distribution and monetization of the finished applications. When Google released Android in competition, they also embraced this approach with their app store and SDK, which also leveraged the entire Google platform and its services. </p>\n<p>Developers could tap into Google's search and maps services, as well as email, etc. Native applications served their purpose superbly and became the primo factor that propelled Android and iOS as the big two phone operating systems at the time, until the present day.</p>\n<p>Native smartphone applications were so common that Apple coined the tagline \"There is an app for that\" and copyrighted it in 2009. </p>\n<p>However, come the 2010s. Web technologies saw increasingly rapid growth. Server-side rendered web pages allow for the creation of full-fledged web applications that could offer business values beyond static information. The responsive design movement also enhances accessibility for these web apps across all platforms. It was also during this time that mobile applications became stagnant. Your phone started to have <em>too</em> many applications, and not all of them were equally useful. Some are thin clients to web services, which you could access using your mobile web browser instead. </p>\n<p>Recognizing this, Progressive Web Applications, or PWA, came in to bridge the gap between native and web applications.</p>\n<h2 id=\"what-are-progressive-web-apps-pwas\" style=\"position:relative;\"><a href=\"#what-are-progressive-web-apps-pwas\" aria-label=\"what are progressive web apps pwas permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What are Progressive Web Apps (PWAs)?</h2>\n<p>First and foremost, PWAs are web applications. They run in web browsers, but also usually in webviews on smartphones. Compared to traditional websites that you would visit with a conventional web browser, progressive apps tend to be a little more low key. </p>\n<p>You may see one through a direct URL, but more commonly through a desktop/home screen icon on your phone, which takes you to a webview hosting the application. By extension, PWAs are now also distributed through app stores, standing alongside native apps.</p>\n<p>The webview itself may also be without or with minimal menu bars to provide an impression close to navigating a native application. Furthermore, progressive applications usually come with some offline viewing capabilities, allowing you to interact with the app even when you are offline or in limited network availability. This is implemented using service workers that stand in between network requests and the user and handle caching as well as push notifications, providing a user experience similar to native app caching.</p>\n<p>With that in mind, the idea behind <a href=\"/build-pwa-using-vanilla-javascript/\">PWA is to create applications</a> that would be most accessible, through the web, that also offers an experience as close to native applications as possible.</p>\n<h2 id=\"why-progressive-app\" style=\"position:relative;\"><a href=\"#why-progressive-app\" aria-label=\"why progressive app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Progressive App?</h2>\n<h3 id=\"ease-of-development-and-distribution\" style=\"position:relative;\"><a href=\"#ease-of-development-and-distribution\" aria-label=\"ease of development and distribution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Ease of development and distribution</h3>\n<p>Suppose you are a new company looking to create a mobile application for your product. If you would like to distribute your app on all major mobile platforms - namely both iOS and Android - you would then have to go through the development and distribution process for both. First off, you will need to learn the language to develop Android applications (Java, Kotlin) and then iOS (Objective-C, Swift), have the correct hardware to test and develop. </p>\n<p>This process will have you relearn everything about one platform on the other. Once you finish the initial product, you will have to maintain both codebases moving forward to complete this.</p>\n<p>With a progressive app, the process becomes a lot simpler. Your application lives within a browser, and hence only needs to be supported by the browser standards. As of now, support for PWAs is available across major browsers: Google Chrome, Mozilla Firefox, Apple Safari, Microsoft Edge, and Firefox (for Android). </p>\n<p>Your language is the language of the web: JavaScript. The choice is also yours to leverage the JavaScript platform you are most familiar with, be it React, Angular, or something completely different. The JavaScript codebase will then become the only codebase you need to maintain for the app.</p>\n<p>Alongside this, you also gain the advantage in the availability of the application. With PWA, your app will be available on the web, accessible by users across many platforms, including all mobile devices that have browser support.</p>\n<h3 id=\"portability\" style=\"position:relative;\"><a href=\"#portability\" aria-label=\"portability permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Portability</h3>\n<p>PWAs live on the web; this means you do not need to download and store many executables and assets on your device, saving you precious storage space if you are using the app on your phone. This is especially useful when the native version of the application is simply a portal to a web service, which serves to make API calls and present data based on the user data on the server only, without performing any device-specific actions. The functionality of these applications is not inhibited by the browser's sandbox and thus make for perfect PWA candidates.</p>\n<h3 id=\"user-experience\" style=\"position:relative;\"><a href=\"#user-experience\" aria-label=\"user experience permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>User Experience</h3>\n<p>PWAs are designed to be responsive. Even though this depends largely on the individual developer of the application, a well designed and developed PWA should, in theory, provide a consistent experience across devices. With native apps, a lot of effort will be required to ensure that the user experience is uniform across multiple platforms. And even then, certain platforms will impose their own set of requirements on the UI look-and-feel, as well as the functionality of the app.</p>\n<h2 id=\"so-why-not-progressive-app\" style=\"position:relative;\"><a href=\"#so-why-not-progressive-app\" aria-label=\"so why not progressive app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>So, why not Progressive App?</h2>\n<p>Progressive apps are a creative solution to smooth out the differences between a native app and the web, but not necessarily replace native apps. While it inherits all the advantages and features of the web, there are still certain disadvantages that need to be considered when deciding between a progressive app or a traditional native app.</p>\n<h3 id=\"leveraging-device-specific-features\" style=\"position:relative;\"><a href=\"#leveraging-device-specific-features\" aria-label=\"leveraging device specific features permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Leveraging device-specific features</h3>\n<p>For one thing, progressive apps are designed to be uniform across devices. This means it is not the technology's focus to make use of specialized features that are available only on select devices. Its feature set will be the lowest common denominator of the range of devices that it supports. With how diverse the feature sets are on modern devices like smartphones and tablets, with high-resolution cameras or fingerprint sensors, to name a few, it would be amiss for applications not to take advantage of these features. It follows that progressive apps are not ideal for specialized workflows, while their strength is in general purpose applications.</p>\n<h3 id=\"browser-compatibility\" style=\"position:relative;\"><a href=\"#browser-compatibility\" aria-label=\"browser compatibility permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Browser compatibility</h3>\n<p>Compatibility is another big-ticket item. At a baseline level, PWA should be supported by all major browsers. However, platform differences still exist, where specific features are supported by one browser but not another, which will cause inconsistencies in behavior when the user switches from one device/platform to another. A prominent example of this being push notification support on iOS, which requires jumping through some hoops to make it work, as Apple does not support this directly. With that in mind, the subtle differences between browser support become a limitation similar to the difference between native app platforms itself.</p>\n<h3 id=\"distribution\" style=\"position:relative;\"><a href=\"#distribution\" aria-label=\"distribution permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Distribution</h3>\n<p>For applications to reach the hands of the users, it needs a distribution platform. For native applications, the answer to this is straightforward: Apps are distributed through the native app store, be it Google Play Store or iOS App Store. However, for PWAs, it is more complicated. Distribution can be as simplistic as passing around the application's URL, and anyone who knows the link can access the app. This method has the added advantage due to Google and other search engines/web crawlers naturally picking up the app URL and returning it as a search result. </p>\n<p>However, this method is passive and requires the user to know the application beforehand. Developers might prefer the more traditional way of having the app listed in an app store, which is possible but requires them to jump through the same hoops as native applications, following all of the distributor guidelines, which removes its advantage compared to traditional apps.</p>\n<h2 id=\"to-pwa-or-not-to-pwa\" style=\"position:relative;\"><a href=\"#to-pwa-or-not-to-pwa\" aria-label=\"to pwa or not to pwa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>To PWA, or not to PWA</h2>\n<p>So with everything considered, should you go the route of the progressive app? We do not aim to give a concrete answer, but instead a suggestion: If your application can be made a PWA, it is a good idea to do so. At the current moment, progressive apps are an evolution of web apps. Compared to the feature set that users are already familiar with in native apps, progressive apps still trail behind. </p>\n<p>This means that if the scope of the application is complex enough, PWA may not provide you with enough tools to do the job. With that said, if your application can be fully implemented with the set of tools that PWA provides, then going this route may net you added benefits that are unique to progressive apps. Are progressive apps the future? It definitely has the potential, but a large part of that answer depends on whether we can leverage its platform to build productive solutions with it today.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"February 04, 2021","updated_date":null,"title":"PWA vs Native App: Which one is Better for you?","tags":["Progressive App","PWA","JavaScript"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/ff88b75a03f86a1891a9545ba6dcd4c4/ee604/index.png","srcSet":"/static/ff88b75a03f86a1891a9545ba6dcd4c4/69585/index.png 200w,\n/static/ff88b75a03f86a1891a9545ba6dcd4c4/497c6/index.png 400w,\n/static/ff88b75a03f86a1891a9545ba6dcd4c4/ee604/index.png 800w,\n/static/ff88b75a03f86a1891a9545ba6dcd4c4/f3583/index.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Nathan Nguyen","github":"nathannguyenn","avatar":null}}}},{"node":{"fields":{"slug":"/engineering/build-pwa-using-vanilla-javascript/"},"html":"<p>Today we will learn about the progressive web app, a very interesting and trending topic in current times,  We will start with the basic steps first on how Progressive Web App works with vanilla js. Also, we’ll cover the concept of PWAS without using any of the frameworks, it's just a plain <code>vanillaJS</code>.</p>\n<h2 id=\"what-are-progressive-web-apps\" style=\"position:relative;\"><a href=\"#what-are-progressive-web-apps\" aria-label=\"what are progressive web apps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What are Progressive Web Apps?</h2>\n<p>A Progressive Web app is an application which is built on top of <em>HTML</em>, <em>JS</em> and <em>CSS</em> with some extra features like <code>service worker</code> and <code>manifest.json</code> file. These extra features will give the ability to run the web application offline.</p>\n<p>Various big companies are moving towards the progressive web app instead of native apps, as it gives some much flexibility to end-users. In some websites you can find the + icon at the right side of the address bar, those are progressive web apps. </p>\n<h2 id=\"setup-your-base-app-for-pwa\" style=\"position:relative;\"><a href=\"#setup-your-base-app-for-pwa\" aria-label=\"setup your base app for pwa permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setup your base app for PWA</h2>\n<p>We will be using <code>npm</code> to start our project, so firstly create a root folder using this command <code>mkdir first-pwa-app</code> or another name of your choice then go to that directory by using this command <code>cd first-pwa-app</code>. Run <code>npm init</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"sh\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm init</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">package name: (first-pwa-app)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">version: (1.0.0)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">description: This is the first PWA example</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">entry point: (index.js): index.html</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">test</span><span class=\"mtk1\"> command:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">git repository:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">keywords:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">author: Mohammed Modi</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">license: (ISC)</span></span></code></pre>\n<p>Once you fill up those details your final output of the <code>package.json</code> file will be below</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;first-pwa-app&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;version&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;1.0.0&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;description&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;This is the first PWA example&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;main&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;index.html&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;scripts&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;test&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;echo </span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\">Error: no test specified</span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\"> && exit 1&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;author&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Mohammed Modi&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;license&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;ISC&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>After that, we need to install the <code>serve</code> dependency to serve the application in localhost so install it using npm <code>npm i serve --save</code>. And then add a script in the <code>package.json</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk14\">...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;scripts&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;test&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;echo </span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\">Error: no test specified</span><span class=\"mtk6\">\\&quot;</span><span class=\"mtk8\"> && exit 1&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;serve&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;serve .&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk14\">...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>So finally our application is ready to serve in localhost. Now let's add some <code>html</code> and <code>css</code></p>\n<h3 id=\"setting-up-the-javascript\" style=\"position:relative;\"><a href=\"#setting-up-the-javascript\" aria-label=\"setting up the javascript permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up the Javascript</h3>\n<p>Create a directory for the app and add js, css, and images subdirectories. It should look like this when you’re finished:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">/first-pwa-app   # Project Folder</span>\n<span class=\"grvsc-line\">    /css     # Stylesheets</span>\n<span class=\"grvsc-line\">    /js      # Javascript</span>\n<span class=\"grvsc-line\">    /images  # Image files.</span>\n<span class=\"grvsc-line\">    package.json</span>\n<span class=\"grvsc-line\">    package-lock.json</span>\n<span class=\"grvsc-line\">    index.html</span>\n<span class=\"grvsc-line\">    manifest.json</span>\n<span class=\"grvsc-line\">    sw.js</span></code></pre>\n<p>You will understand the use of <code>manifest.json</code> and <code>sw.js</code> files once we move ahead in this tutorial.</p>\n<h3 id=\"add-some-code-for-app-interface\" style=\"position:relative;\"><a href=\"#add-some-code-for-app-interface\" aria-label=\"add some code for app interface permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add Some code for app interface</h3>\n<p>When writing the code for Progressive Web Application we need to keep in mind two requirements</p>\n<ol>\n<li>The landing page should have some content even if the javascript is not loaded</li>\n<li>The App should be responsive and can be properly interactive in any device.</li>\n</ol>\n<p>For this app, to handle the first requirement we will add the static text in the Html page and for the second requirement, we will use the viewport.</p>\n<p>So let's add this code inside the <code>index.html</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;utf-8&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">My First PWA</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;css/style.css&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fullscreen&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">My First PWA!</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Next, we need to create a file <code>css/style.css</code> and paste this code inside this</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">body</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-family</span><span class=\"mtk1\">: </span><span class=\"mtk8\">sans-serif</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/* Make content area fill the entire browser window */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/* Make content area fill the entire browser window */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">html</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.fullscreen</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">flex</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/* Center the content in the browser window */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.container</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin</span><span class=\"mtk1\">: </span><span class=\"mtk8\">auto</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.title</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3rem</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Once you add the code save all the files and run the script <code>npm run serve</code> which will start your application in <code>http://localhost:5000/</code></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 80.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAABbElEQVQ4y8WUy2rCQBSG8yCikmiSjpPEBLPrQuiq9DWkbxB7odA2bZ/Jnasq8bITfAe3Kgpe8jdzYCRqK9FND/zMwMDHdzgzo7yHnwg/vvD6FiJM9k/PLwiaj2j+kiB4oPNG4x6sYoFbDq2McRSLKu0VXFCj0Qh+zYPnVmGaJhzHBuccnudB2W63yJrVakXAzncHls1Rv6nDtjg0TYOu6yiXy1DiOEbWbDYbAkbdLnSniuvbO3DGoKoqQUUIKEqup0oCe71eAjJRcy1qWdgZhkE5Av5ldwS0KnD9WjIQRmalUomipM1OWaZbFkABMa4YGcp2dy2nLWazGabTKebzORaLBa3L5XLPMIoi5PN5MpJ2R0AxRVHD4RCtVgvj8Rj9fh/tdhuTyYTO1uv1DlgoFGiqaejFLUtDCUznoqGcBcxybf4PmPmlHAxlD5jV7tAwl8vRkzuMIq/LOYaDwYB+F9/34boubNtOfhyH8gPOd+KYkgDmUgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"First Build\"\n        title=\"First Build\"\n        src=\"/static/328993f8670367e5593427d2344d31d6/e5715/1.png\"\n        srcset=\"/static/328993f8670367e5593427d2344d31d6/a6d36/1.png 650w,\n/static/328993f8670367e5593427d2344d31d6/e5715/1.png 768w,\n/static/328993f8670367e5593427d2344d31d6/53e84/1.png 2074w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"testing-the-app\" style=\"position:relative;\"><a href=\"#testing-the-app\" aria-label=\"testing the app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Testing the App</h3>\n<p>As we can see our application is running in the browser, let test it using the <a href=\"https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=en\">LightHouse Extension</a> in Google Chrome browser. For the best result, I recommend testing in an <strong>incognito tab</strong> of google chrome.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 58.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABuklEQVQoz5WS3Y4SQRCFeQtuRIb5H5jp+elp1sVkE5P1VTS+gOia1QtXfbfdGbiFfQ8gZIHjqVkhIeqKlVQq3Ul/dU51tb7efMfNtx+4/vwF4/FHjD9cHeV73l19usabt++QqAxpmh8yjhUc18do9BKXl69xcfEKLZwY9/MZhjrD6PwMxpTIsgz9fh++7yMIAnieyyYKrc1mg30+PPye6/W6Ad7d3qIfBggIsCwL3W4XnU6nqc+eW2i327BtG63dboenUhpJ1HWNTOcojUGhdZNRFKHX68Fx7KaWZfloWR7+LQ7AqoIKQ+h4gDJJoFWCkGcBiTJR2gD3MKmLxQLL5bKpq9XqSOFkMoEZGkScl03LDkF72B+B2+0W0+kUs9msyfl83gDlXqKq7qCoThcFdJ6jkErbotImWOZqOI7TLXOGWikUgwFiz4PrOOhRmfVLqSiUBkeWn/wUzjBPUxS0lVGdIjwkMOKH+ExRmHC2hz38F7AisOCDF7R7XuQ44x4mvoeEaiOqFaVxHJ9uuaorpFyboS5hqNLQnmID2UvHflT4X8CawISfIrbkoXyG67rcQQcuVTqux/sEPwHkdpQSGWEwNAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"First Test\"\n        title=\"First Test\"\n        src=\"/static/7e9a07953900a7deec8b038fe9524e96/e5715/2.png\"\n        srcset=\"/static/7e9a07953900a7deec8b038fe9524e96/a6d36/2.png 650w,\n/static/7e9a07953900a7deec8b038fe9524e96/e5715/2.png 768w,\n/static/7e9a07953900a7deec8b038fe9524e96/d9ed5/2.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>As you can see we have green signals for both of our above requirement:</p>\n<ol>\n<li>Has a <meta name=\"viewport\"> tag with width or initial-scale</li>\n<li>Contains some content when JavaScript is not available</li>\n</ol>\n<p>But still, there is lots of work to do, so let's start with the first feature of PWA's.</p>\n<h3 id=\"adding-a-web-app-manifest\" style=\"position:relative;\"><a href=\"#adding-a-web-app-manifest\" aria-label=\"adding a web app manifest permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Adding a Web App Manifest</h3>\n<p>Let's create a new file called <code>manifest.json</code> in the root of our application. To understand more about the manifest file check out [this doc]</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;My First Progressive Web app&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;short_name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;First PWA&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;lang&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;en-US&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;start_url&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;/index.html&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;display&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;standalone&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;background_color&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;white&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;theme_color&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;white&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Now update the <code>index.html</code> head tag by adding the manifest.json file as a link</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;manifest&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/manifest.json&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>We should also declare the theme colour which should match with your manifest.json file as <code>meta tag</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;theme-color&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;white&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Once you run the lighthouse test again you can see we got green signals in some points like</p>\n<ol>\n<li>Sets a theme colour for the address bar.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 58.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABuElEQVQoz5WTWW7bMBiEfYv0xdFqWdQuUopRB2jRB18m6A2cNjDykOVohuxnu72GDcPwMhnSC4o2bRMCAwEC+HFmfrL18PiMx6dnjEb3GN5+x+1vGg6/4e5uhJubr8jyEkUhjXIqSXP4foB+/xqDwQCfPn9BC29cP3/M0FMl+h97qKoKRZ4jigSCIEDQ7RLsI8sytLbbLbQ2m82rWq/XBjgejxGJEF0CHMeBbdu4bLdhWTba1MXFB7iui9Z+v8e/pA/TazKZoFQSVX0FqZSREAIu4Z7nmkO0cxNZb/zbOgObBhmjyTiCTBKoNIUIQ9gEaWeWZR2AJ5j+LhYLLJdLo9VqdXC4OwKnU9S9GoJQ17HhEaRdOYSdgIquz8DdbocpN81mM6P5fG6A+r9eDR0WaYJKSqiyRM3vVaVMr6dO3xeZHUpOsUxiRJ0OBKcqfA++e+jvD4f/HQodqiKnq8q4zNmjju0eY2uHKXs938PXYL86bOhQyQJ9Tvq6rqEyDsXzENCpc3SZ8JA3R24mDZIy4yvha2GHJV3GBHQY33TIyO8C6g4rdqSLVxoWxwh5bfRLCUO+mDA2kV8AAfuU5aBuRe0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Improving the Application\"\n        title=\"Improving the Application\"\n        src=\"/static/1a6d6e4f756d84ce7645f20d106d8b3b/e5715/3.png\"\n        srcset=\"/static/1a6d6e4f756d84ce7645f20d106d8b3b/a6d36/3.png 650w,\n/static/1a6d6e4f756d84ce7645f20d106d8b3b/e5715/3.png 768w,\n/static/1a6d6e4f756d84ce7645f20d106d8b3b/d9ed5/3.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"app-icons\" style=\"position:relative;\"><a href=\"#app-icons\" aria-label=\"app icons permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>App Icons</h3>\n<p>Still, we need to add more attributes to our <code>manifest.json</code> files like <strong>icons</strong> so let's add the icons inside the <code>images</code> folder, I have used to icons <code>pwa-icon-256.png</code> and <code>pwa-icon-256.png</code> for this demo you can find in this repo. You can use various sizes in it. And finally, add the <code>favicon.png</code> in the root of the project.</p>\n<p>So let's add the <code>icons</code> attribute after the <code>short-name</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;My First Progressive Web app&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;short_name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;First PWA&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;icons&quot;</span><span class=\"mtk1\">: [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;src&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;.images/pwa-icon-256.png&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;sizes&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;256x256&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;type&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;image/png&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;src&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;.images/pwa-icon-512.png&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;sizes&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;512x512&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">&quot;type&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;image/png&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;lang&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;en-US&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;start_url&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;/index.html&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;display&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;standalone&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;background_color&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;white&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;theme_color&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;white&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>And the index.html will head can will look like</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;apple-touch-icon&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;images/pwa-icon-256.png&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>You can also verify the <code>manifest.json</code> file by opening Chrome DevTools, in the <strong>Application Tab</strong>, the first tab in the sidebar <strong>manifest</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 121.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAYAAAD6S912AAAACXBIWXMAABYlAAAWJQFJUiTwAAADbUlEQVQ4y41VyU7jUBD0dwBCJCGb7diOncSOsxL2JSAkhu9h/gDOLDckOCCExIHhyAUuiE+q6erkRYbJYQ6t5+fY5arq6hdrd3cXSZKg2Wyi2+2i1WohTVMkcaz3G42GViz7lZUVFAoFLC0twfd89JsR0qSOlvwWRaE+Zx0fH2Nvbw+bm5sK0G63tTqdDmq1GuJ2iuFoHWm3h2KxqICrq6u65ln5wuQ6n0elUoE1Ho9xcvILp6enODjYx2AwUECy9TxPylf2tm3rS3zZFIFNFaSq1SqsjY0NlcgiSBiGqNfruvKBIBBp/b7eI8NyuYySFFcC5XM5/VBOVt6zxoeHyore0QMCRVGk17ZdRdK00R8O0ekPVH6SdtDpDdSCehjBdly4Yo3j1uD7ASw2hSxHo5H6SPMJSkDHseHYRXi+D78eoibyWX4QSNUz15M9P2Dt7OyIdwc4OjrC+vq6+mUA6ZsnXw1Fbk46nM/nZg2Y7CdStWRfKpVgbW9vK0OyIwi9MpIdx1GfjHeOyKuHDUSNJuIkRaMVoxknqIjX/JA2hZExOSQzUwQlILNHULJlhQJGwGyHTYw0Nnv7+xjSdMldr9dDc9oYw5AgZM1rExdKnQeoDCl1JN5xpXSCZj1UVrIPxHh6xD0Db0D+YchgE6QnGeTa+MHQjJvjugLkossPih3Kdp5kslpbW8O+SN/a2lL5WUAjhcV9W3JYKldQmMrOjqICGqlsDrPIgFOekUyZrrAjIPdxpqtzm0JWBOLKCJEtZ5ldJyM2gLGhb9UfQNmZ/sZwOFxTMLKkZBMjAjK0PFXIjkyZvVbSnttlDTZBKJPRyBZzqF0W0IqEOjc9BDgt+dn1dD89hQhssRmUrN0VkGhaxkOyCmVGJ132ZH49HUfON2fZkxl25X6pVFZQi2C+/BhlwLI5JECSdlVmS8YtEPaBHBQ8EAgay/1EPC+LfwrIDhuJ2dHT2AggZ9jTU8ZTBZeXl3h5ecHj4yNeX//g99mZesfGqWSeMIzJXEDxjw+6sjrTifn6+sL19TXu7+/x9PSkwAsLC7PmfAPMgmZPG7Kk8YzO+/s7rq6ucHt7i4eHB9zd3emf1lyG8wDNQcARZIM+Pz9xfn6Om5sbBSXDxcXF/wek0ebfjvvn52d8fHzg7e1NwS8uLrC8vDwD/As3uxARKwst4AAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Application Manifest\"\n        title=\"Application Manifest\"\n        src=\"/static/1fa7bbfafde2b8b0c2a364cca9c89f36/e5715/5.png\"\n        srcset=\"/static/1fa7bbfafde2b8b0c2a364cca9c89f36/a6d36/5.png 650w,\n/static/1fa7bbfafde2b8b0c2a364cca9c89f36/e5715/5.png 768w,\n/static/1fa7bbfafde2b8b0c2a364cca9c89f36/fbf76/5.png 1252w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>After running the test again, we can see all the <code>manifest.json</code> related issues are solved, The remaining issues can be resolved by adding the service worker.</p>\n<h3 id=\"adding-service-worker\" style=\"position:relative;\"><a href=\"#adding-service-worker\" aria-label=\"adding service worker permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Adding Service Worker</h3>\n<p>The next requirement of our app will be the service worker. The service worker is a script that runs in the background without any user interaction.</p>\n<p>The task of service worker will be to download and cache our content and then serve it when the user is offline. To understand more on service workers you can check this doc <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API\">from mozilla</a>.</p>\n<p>To integrate service workers we need to create a file called <code>sw.js</code> in the root of our project.</p>\n<blockquote>\n<p><strong>Note</strong>: Service worker will only have the access to the files of the <strong>current and sub-directories</strong> hence we need to place it in the root of our project</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">cacheName</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;my-first-pwa&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">filesToCache</span><span class=\"mtk1\"> = [</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;/index.html&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;/css/style.css&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;/js/main.js&quot;</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/* Start the service worker and cache all of the app&#39;s content */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">self</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;install&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">waitUntil</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">caches</span><span class=\"mtk1\">.</span><span class=\"mtk11\">open</span><span class=\"mtk1\">(</span><span class=\"mtk12\">cacheName</span><span class=\"mtk1\">).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">cache</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">cache</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addAll</span><span class=\"mtk1\">(</span><span class=\"mtk12\">filesToCache</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/* Serve cached content when offline */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">self</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;fetch&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">respondWith</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">caches</span><span class=\"mtk1\">.</span><span class=\"mtk11\">match</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">request</span><span class=\"mtk1\">).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">((</span><span class=\"mtk12\">response</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\"> || </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">request</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>The first 2 variables <code>cacheName</code> and <code>filesToCache</code> are used to create an offline cache in the browser. <code>cacheName</code> is used to create a cache of specific name and <code>filesToCache</code> will be the list of files that we need to cache, <code>/</code> will store the root files that is <code>index.html</code> even if the user does not specify the file name in the URL and then all other files specified in the array.</p>\n<blockquote>\n<p><strong>Note</strong>: Here I have used the <code>filesToCache</code> array as a list of static files just to demonstrate the purpose of PWA, it will stop working in production if even one file fails to load.</p>\n</blockquote>\n<p>Finally, we will load our service worker, for that create <code>js/main.js</code> file and copy the below code.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk11\">onload</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;use strict&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk8\">&quot;serviceWorker&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk12\">navigator</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">navigator</span><span class=\"mtk1\">.</span><span class=\"mtk12\">serviceWorker</span><span class=\"mtk1\">.</span><span class=\"mtk11\">register</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;./sw.js&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<p>And add this script in the <code>index.html</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;js/main.js&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>So the final version of our <code>index.html</code> file will look like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;utf-8&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Hello World</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;apple-touch-icon&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;images/pwa-icon-256.png&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;css/style.css&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;manifest&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/manifest.json&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;theme-color&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;white&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;fullscreen&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Hello World!</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;js/main.js&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Now our application is made as fully PWA supported, you can verify it by running the lighthouse test.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 58.769230769230774%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAAB4ElEQVQoz42SXWsaQRSG/RFNum4I3Zn9/nI/dFeTDYUYKJQW8ldCb1ITelXb/kPBCy9T9cY7Lbjq2zOz1W5Kiz3wMMxcPLxnzmkMv3zD5+FXDImHx0+4//hQcT/AYPCIu7sP6GRdhGGEOE7RihJERJy05d22Xbiuj37/BtfXfTRwpH6slnj/9g3yTht5niFKIvihB8s24XgOLMeEaZmwTMKy0NhsNqhTlhXr9VoKvz89IUsTqM0mVF2FwhScnL+AHdtQeROn5yf09hKKqkBRFDR2ux3+xna7lcL5fI4sy6CeqeAeg8EN+I6Pd7e36HZ70DUD3OHgFgNnvGpZCP6s/dtsNkNRFPRXNqyI2mqZCDsB3NhBQKcdu2CBDo2/gqaxKqGosiyxXC6xWq0k4i6F0xkurgrE1HbezdHO2giiAIxr4AJdg64zMErHOf8tXCwWGI1GmEwmGI/HUl4JpyS8pCFYCHwfvsDz4RomPF2X2CRijFXCoy2T8PLmNUKarqEblKxKIk6NJIK97FnCfw1FtNyjhFESI01T2r3qdF23Ev0SHhIeE05pKFc0lDRJpEy0bNLOsZqozjNhvQ4JSdgrLhBGLbk+AsMwaKLaoc06/yUUQ/HDQCYUhGEo16iedC/8CYFTXfCHL/ezAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Full PWA Supported\"\n        title=\"Full PWA Supported\"\n        src=\"/static/909cf0352662de4275cd17be5d1e96c0/e5715/6.png\"\n        srcset=\"/static/909cf0352662de4275cd17be5d1e96c0/a6d36/6.png 650w,\n/static/909cf0352662de4275cd17be5d1e96c0/e5715/6.png 768w,\n/static/909cf0352662de4275cd17be5d1e96c0/34e83/6.png 2852w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"finishing-up\" style=\"position:relative;\"><a href=\"#finishing-up\" aria-label=\"finishing up permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Finishing Up</h4>\n<p>We are done with the code, now the last thing remaining in to host it in any of the <code>https</code> domain. As the PWA will be required to run in <a href=\"/everything-you-want-to-know-about-authorization-headers/\">the secure domain</a>.</p>\n<p>You can get the full source code of this example in this <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/ProgressiveWebApp/MyFirstPWA\">Github repo</a></p>\n<p>I hope you enjoyed the progressive web apps using vanilla js tutorial and found it useful. Please let me know what you think in the comments below.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk14 { color: #F44747; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"June 26, 2020","updated_date":null,"title":"How to Build a PWA in Vanilla JS","tags":["PWA","JavaScript"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/1c496ce8fd476e70f4dbf1a97f08619a/ee604/cover.png","srcSet":"/static/1c496ce8fd476e70f4dbf1a97f08619a/69585/cover.png 200w,\n/static/1c496ce8fd476e70f4dbf1a97f08619a/497c6/cover.png 400w,\n/static/1c496ce8fd476e70f4dbf1a97f08619a/ee604/cover.png 800w,\n/static/1c496ce8fd476e70f4dbf1a97f08619a/f3583/cover.png 1200w,\n/static/1c496ce8fd476e70f4dbf1a97f08619a/e4d72/cover.png 1280w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Mohammed Modi","github":"mohammed786","avatar":null}}}}]}},"pageContext":{"tag":"PWA"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}