<p>Per wikipedia,</p><blockquote><p><span style="color: rgb(77, 81, 86); font-family: Roboto, arial, sans-serif; font-size: 14px;">A progressive web application is a type of application software delivered through the web, built using common web technologies including HTML, CSS and JavaScript. It is intended to work on any platform that uses a standards-compliant browser, including both desktop and mobile devices.</span></p></blockquote><p>One of an interesting feature on PWA is that we can add PWA compliant web app into desktop and these behaves like native/desktop apps. This feature is expecting to optimizing conversion rate, as the app is no longer playing in web browser. That said, one concern we should consider is that user does not know that if a certain web application is PWA compliant and we would need to enable push notification to tell user to add the app to desktop. That kind of notification in web app typically is annoying user.</p><p><br></p><p>Also another note is that it is very slow implementation to apple. Regarding iOS, only safari is capable to install the app to desktop, and other browser like google chrome and firefox are not capable right now, while android phone is fully implemented(and as you can guess, it's from politics, web vs desktop app).</p><p><br></p><h3>How do we know if my web app is PWA compliant?</h3><p>Google chrome does verify these. Go to development console (Alt+Cmd+i), selecting "Lighthouse" and push "generating report" then lighthouse automatically does audit and report out PWA readiness as one of report like below. Don't complain about bad performance for now!! </p><p><img src="/media/django-summernote/2021-01-15/1e06cf4e-5c1f-4c35-9363-ce31b069f110.png" style="width: 100%;"></p><p><br></p><p>I will how you how to implement PWA features to web apps using react app as an example from next sections.</p><p><br></p><h3>Step0 : Overall Requirement</h3><ol><li>https communication : need to enable https communication to encrypt communication between UI and server</li><li>desktop icon in manifest file : prepare additional icons for desktop once we add the web app to desktop </li><li>service worker : prepare service worker system so they could decide when to communicate to server</li></ol><p><br></p><h3>Step1 : HTTPS</h3><p>PWA requires HTTPS communication. For a hosting service from github or firebase, it originally goes with HTTPS rather than HTTP, while heroku free app goes with HTTP. If your hosting service does not give you SSL certificate to change from HTTP to HTTPS, there are couple of free SSL service in a web. For a heroku, if you could upgrade to next grade ($7/mo), the service gives you SSL certificate and it automatically redirect to HTTPS. If you are getting your private domain, make sure to use https to set route with redirect from http to https. I'm putting google domain as an example.</p><p><img src="/media/django-summernote/2021-01-15/97f67403-2875-422f-8fe3-2e42da06e24a.png" style="width: 100%;"></p><p>If your system has backend server, we can also force them to use https. Below are example for express server.</p><pre>npm install express-sslify</pre><pre>//server.js const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const path = require('path'); const enforce = require('express-sslify'); //<= ADDED! if (process.env.NODE_ENV !== 'production') require('dotenv').config(); const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); //library to process backend node serer const app = express(); const port = process.env.PORT || 5000; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(enforce.HTTPS({ trustProtoHeader: true })); //<= ADDED! //for development server app.use(cors()); //set how to server an application in production if (process.env.NODE_ENV === 'production') { app.use(express.static(path.join(__dirname, 'client/build'))); app.get('*', function(req, res) { res.sendFile(path.join(__dirname, 'client/build', 'index.html')); }); } app.listen(port, error => { if (error) throw error; console.log('Server running on port ' + port); }); //client side send token thru /payment app.post('/payment', (req, res) => { //req object const body = { source: req.body.token.id, //token amount: req.body.amount,//total amount currency: 'usd' }; stripe.charges.create(body, (stripeErr, stripeRes) => { if(stripeErr) { res.status(500).send({ error: stripeErr }); //500 failure status } else { res.status(200).send({ success: stripeRes }); //200 no failure } }) })</pre><p><br></p><h3>Step2 : Prepare desktop icon</h3><p>In the manifest under 'public' folder in react app folder, we need to add extra icon info and add that size of image file</p><pre>//manifest.json file { "short_name": "Mionosuke", #your app name in desktop "name": "Mionosuke Japanese Traditional EC", "icons": [ { "src": "favicon.ico", #this is original icon used for web tab "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" }, { "src": "mionosuke-pwa-512x512.png", #this is new icon for desktop app "sizes": "512x512", "type": "image/png" }, { "src": "mionosuke-pwa-192x192.png", #this icon is defaul to desktop app "sizes": "192x192", "type": "image/png" } ], "start_url": ".", "display": "standalone", "theme_color": "#ffffff", "background_color": "#ffffff" } </pre><div>For iOS, however, these statement in manifest does not work yet and we need to add 1 line of code in index.html under 'public' folder.</div><pre>//index.html file <link rel="apple-touch-icon" sizes="180x180" href="mionosuke-pwa-192x192.png"></pre><p>Also, make sure that you add new icon image to 'public' folder so either manifest or index.html can find the image in production</p><p><br></p><h3>Step3 : Prepare service worker</h3><p>Current create-react-app (>v4) and React (>v17) does not have serviceworker file as a default and we need to have these file. In order to get these file, do following code when you create a new react app</p><pre>npx create-react-app <your app name> --template cra-template-pwa</pre><p>If you've already had your react app without serviceworker file, you can copy necessary files from new react app. In the case, copy the 'service-worker.js' and 'serviceWorkerRegistration.js' file from the new created app and add it into src directly under your react app. Also copy the all the 'workbox-*' dependencies from the package.json file in the dependencies section and add it into your package.json dependencies, then</p><pre>npm install</pre><p>and re-install library based on updated dependencies.</p><p>Then you need to add following code to server.js</p><pre>//server.js app.get('/service-worker.js', (req, res) => { res.sendFile(path.resolve(__dirname, '..', 'build', 'service-worker.js')); });</pre><p>also indstall serviceWorker library in the app so use index.js to declare library install</p><pre>import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import {store, persistor} from './redux/store'; import * as serviceWorker from './serviceWorkerRegistration'; //<= ADDED! import './index.css'; import App from './App'; ReactDOM.render( <Provider store={store}> <PersistGate persistor={persistor}> <React.StrictMode> <App /> </React.StrictMode> </PersistGate> </Provider>, document.getElementById('root') ); serviceWorker.register(); //<= ADDED!<br></pre><p><br></p><div>That's it!</div>
<< Back to Blog Posts
Back to Home