{"componentChunkName":"component---src-pages-markdown-remark-fields-slug-js","path":"/engineering/guest-post/how-to-build-a-progressive-web-app-with-react/","result":{"data":{"markdownRemark":{"id":"18b8ae06-3475-5811-bd96-45036dacd1a3","excerpt":"A Progressive Web App (PWA) is a more dynamic web application that can run as a standalone. It offers benefits such as:  performance; the ability to work with…","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>","headings":[{"value":"Create a React App with the Progressive Web App Template","depth":2},{"value":"Adding a Simple React Component","depth":2},{"value":"Running Your Application","depth":2},{"value":"Running Your Progressive Web Application","depth":2},{"value":"PWA Features","depth":2},{"value":"Conclusion","depth":2}],"fields":{"slug":"/engineering/guest-post/how-to-build-a-progressive-web-app-with-react/"},"frontmatter":{"metatitle":null,"metadescription":null,"description":"Follow this article to understand how to develop a simple React PWA. It explains the step-by-step process to help you easily follow along.","title":"How to Build a Progressive Web App (PWA) with React","canonical":null,"date":"October 22, 2021","updated_date":null,"tags":["React","PWA","npm"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/c7e3ca9131877e6d122821800050a259/03979/blog-image.png","srcSet":"/static/c7e3ca9131877e6d122821800050a259/f5f11/blog-image.png 200w,\n/static/c7e3ca9131877e6d122821800050a259/6d133/blog-image.png 400w,\n/static/c7e3ca9131877e6d122821800050a259/03979/blog-image.png 800w,\n/static/c7e3ca9131877e6d122821800050a259/aca38/blog-image.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Abdullah Pathan","github":"aonepathan","bio":"He is a full-stack developer and an avid learner. He is well-versed in web technologies and is currently working with React. In his free time, he loves playing Halo.","avatar":null}}}},"pageContext":{"id":"18b8ae06-3475-5811-bd96-45036dacd1a3","fields__slug":"/engineering/guest-post/how-to-build-a-progressive-web-app-with-react/","__params":{"fields__slug":"engineering"}}},"staticQueryHashes":["1171199041","1384082988","1711371485","1753898100","2100481360","229320306","23180105","528864852"]}