Intro to (Progressive) Web Apps
Tags: pwa, webdev, html, javascript
Published: 2020-05-18 20:55:46

<h2>How to start Web Development?</h2>

<p>Say hello and get to know the concepts of the Internet, IP, WWW, Browser, Client-Server Architecture, HTTP(S), DNS, Search Engine, URL, API.</p>

<h3>Web page</h3>
<p>A document which can be displayed in a web browser, written in the HTML language, identified uniquely on web using URL.</p>

<h3>Website/Web App</h3>
<p>A Website or A Web app is a collection of web pages.</p>

<h3>Web server</h3>
<p>A computer that hosts a website on the Internet.</p>

<h3>Technologies used and their standards</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/i/gb45i7zummyfcn8lxzxu.jpg" />

<h4>HyperText Markup Language (HTML)</h4>
<p>The most basic building block of the Web. It defines the meaning and structure of web content.</p>

<h4>Cascading Style Sheets (CSS)</h4>
<p>A stylesheet language, describes a web page's appearance/presentation.</p>

<h4>JavaScript</h4>
<p>A lightweight, interpreted, object-oriented language with first-class functions, used in Web pages for describing functionality/behavior. </p>

<h4>WebAssembly</h4>
<p><strong>TL;DR</strong> Running C/C++/Rust code on Web</p>
<p>WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ with a compilation target so that they can run on the web.
</p>

<h4>Web API/ Browser API</h4>
<p>Not part of JavaScript, Provided by the host environment (Browser). The most important one is the Document Object Model (DOM), used to manipulate the document.
There are Fetch (Communicating with server), Client-side storage, Device, Audio/Video, Graphics APIs, Web Workers API (To run a script in a background thread separate from the main execution thread), WebSockets, Server-sent events, Permissions API, etc.</p>
<p>
There are Third-party APIs also (Ex. Twitter API, Google Maps API, etc).
</p>

<h3>Engines used in Major browsers</h3>
<table>
<tr><th>Browser</th><th>Rendering Engine (Transforms HTML & other resources of a web page into an interactive visual representation on a user's device)</th><th>JavaScript Engine (executes JavaScript code)</th></tr>
<tr><td>Chromium, Google Chrome, Microsoft Edge, Opera, Brave
</td><td>Blink</td><td>V8</td></tr>
<tr><td>Firefox</td><td>Gecko</td><td>SpiderMonkey</td></tr>
<tr><td>Internet Explorer
</td><td>Trident</td><td>Chakra</td></tr>
<tr><td>Microsoft Edge (Initial)</td><td>EdgeHTML
</td><td>Chakra</td></tr>
<tr><td>Safari</td><td>WebKit
</td><td>JavaScriptCore (SquirrelFish)</td></tr>
</table>

<h3>What are Progressive Web Apps (PWA)?</h3>
<p>Web apps that are enhanced with native app-like features such as installation, offline support & push notifications. <strong>Website++ </strong>😜.</p>

<ul>
<li>Discoverable - From web search results/ app stores (Google Play Store (using <a href="https://developers.google.com/web/android/trusted-web-activity">TWA</a>), Microsoft Store, etc.)</li>
<li>Installable - Like an app, Install prompt can be customized</li>
<li>Re-engageable - Sends push notifications like native apps</li>
<li>Network Independent - Works offline or in low-network conditions</li>
<li>Progressive (Cross-browser compatibility) - Experience scales up (or down) with device capabilities <strong>using Latest Web APIs</strong></li>
<li>Safe - Only works with HTTPS (You may use letsencrypt.org)</li>
<li>Responsive Design - Adapting to the screen size, orientation & input method</li>
<li>Linkable - Share and launch from a standard hyperlink</li>
<li>Best practices - Improve the Efficiency, follow Semantics, Accessibility (A11y), Internationalization (i18n), Localization (i10n), usage of emerging Web APIs</li>
</ul>

<h4>Why PWAs?</h4>
<ul>
<li>Improved User Experience</li>
<li>Easy to develop & maintain</li>
<li>Cross-platform & native feel</li>
</ul>

<img src="https://dev-to-uploads.s3.amazonaws.com/i/0mqimaynm6a9rgy6mei9.jpg" />
<h4>Let's try one</h4>
The following are the two major components of a PWA.
<ul>
<li><a href="https://developers.google.com/web/fundamentals/primers/service-workers">Service Workers</a>, a type of web worker. It's essentially a JavaScript file that runs separately from the main browser thread, intercepting network requests, caching or retrieving resources from the cache, and delivering push messages.</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Manifest">Web app manifest</a> (A JSON file describing key info about your web app (such as icons, language, and URL entry point))</li>
</ul>

<p>Add a 'manifest.json' file which has a name, icon, color, display (used to customize the browser UI for the app) attributes.</p>
<h6>manifest.json</h6>
```
{
  "short_name": "test",
  "name": "pwa test",
  "icons": [
    {
      "src": "/icon.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/icon.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/",
  "background_color": "#3367D6",
  "display": "standalone",
  "theme_color": "#3367D6"
}
```
<p>'index.html' imports the 'manifest.json' file. Safari has only partial support for manifest config. It takes attributes using meta tags.</p>
<h6>index.html</h6>
```
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>pwa test</title>
  <link rel="manifest" href="/manifest.json">
  <!-- Add to home screen for Safari on iOS -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="pwa test">
  <link rel="apple-touch-icon" href="icon.png">
  <meta name="msapplication-TileImage" content="icon.png">
  <meta name="msapplication-TileColor" content="#3367D6">
</head>
<body>
  <h1>Hi Everyone!</h1>
  <script>
    window.addEventListener('load', async () => {
      if ('serviceWorker' in navigator) {
        try {
          const registration = await navigator.serviceWorker.register('/sw.js');
          console.log('ServiceWorker registration successful with scope: ', registration.scope);
                  } catch (err) {
          console.error(err);
        }
      }
    });
  </script>
</body>
</html>
```
<p>A service worker is registered using 'serviceWorker.register()'. It has 'install', 'activate', 'fetch' events. Let's add 'sw.js'. The 'sw.js' has event handlers which handles the caching of our app.</p>

<h6>sw.js</h6>
```
const dataCacheName = 'pwa-test-data';
const cacheName = 'pwa-test';
const filesToCache = [
  '/',
  '/index.html',
  '/icon.png',
];

//install the sw
self.addEventListener('install', function (e) {
  console.log('[ServiceWorker] Install');
  e.waitUntil(
    caches.open(cacheName).then(function (cache) {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    })
  );
});


self.addEventListener('activate', function (e) {
  console.log('[ServiceWorker] Activate');
  e.waitUntil(
    caches.keys().then(function (keyList) {
      return Promise.all(keyList.map(function (key) {
        if (key !== cacheName && key !== dataCacheName) {
          console.log('[ServiceWorker] Removing old cache', key);
          return caches.delete(key);
        }
      }));
    })
  );
  return self.clients.claim();
});


self.addEventListener('fetch', function (e) {
  console.log('[Service Worker] Fetch', e.request.url);
  e.respondWith(
    caches.match(e.request).then(function (response) {
      return response || fetch(e.request);
    })
  );
});
```
<p>Now, We need a server to host our app. Let's create a simple express.js server. Add 'server.js' which serves the public directory.</p>
<h6>server.js</h6>
```
const path = require('path');
const express = require('express');

const app = express();

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
})

app.listen(7777, function () {
  console.log('Example app listening at http://localhost:7777')
});
```
<p>
Project structure 
<img src="https://dev-to-uploads.s3.amazonaws.com/i/kusmobgqtcs14d4re8dw.JPG" />
</p>
<h5>How to run?</h5>
<ul>
<li>Install Node.js
<li>Launch cmd/terminal & Navigate to the app directory and do 'npm i express' and then 'node server.js'</li>
<li>Launch your browser and visit 'localhost:7777'</li>
<li>Install the app (Click on the install button on URL Bar in case of Chrome)</li>
</ul>

<p>Find the source for the above sample PWA <a href="https://github.com/sudhakar3697/PWA-Sample">here</a></p>

<h4> The companies in the below pic are already delivering PWA!</h4>
<img src="https://dev-to-uploads.s3.amazonaws.com/i/320168xe4k4jr3udjfuh.jpg" />
<a href="https://gsuiteupdates.googleblog.com/2020/05/use-new-google-chat-app.html">Google Chat PWA</a>
<a href="https://web.telegram.org">Telegram Web</a>

<h3>Good to know about</h3>
<ul>
<li><a href="https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/choose-between-traditional-web-and-single-page-apps"> Traditional Web Apps vs Single Page Apps (SPA)</a></li>
<li><a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web"> Server-Side Rendering vs Client-Side Rendering vs Rehydration vs Pre-Rendering</a></li>
<li><a href="https://developers.google.com/web/fundamentals/architecture/app-shell">App shell architecture for PWAs</a></li>
<li>Eager, Lazy and Preloading, Skeleton loading</li>
<li>Lighthouse - An audit tool for web pages</li>
<li><a href="https://www.pwabuilder.com">PWAbuilder - Quickly and easily turn your website into an app!</a></li>
<li><a href="https://developers.google.com/web/tools/workbox">Workbox</a>(Collection of libraries and tools used for generating a service worker).</li>
</ul>

<p>Kindly check out my <a href="https://github.com/sudhakar3697/awesome-web-tech">awesome-web-tech</a> github repo for more resources.</p>

<p>Thanks for reading my very first article 🙏</p>

<h3>References</h3>
<p> MDN, MSDN, Google Developers, web.dev, Wikipedia</p>