Progressive Web Apps. Progressive Web Apps (PWAs) are web applications that load like regular web pages or websites but can offer the user functionality such as working offline, push notifications, and device hardware access traditionally available only to native mobile applications.

  1. Why Native Apps Are Doomed
  2. Google Intro To Progressive Web Apps
  3. PWA Code Lab - My First PWA
  4. Glitch - a free online tool for online app development
Over a series of classes we will turn your weather app into a PWA. This tutorial is based on Google Code Labs.
  1. "Remix" your weather app on Glitch and call the project something like weather-app-pwa.
  2. Run an audit
  3. Add a manifest
    • Create a file named public/manifest.json in your project. Add the following:
    • Add a link tag with rel="manifest" href="/manifest.json" to the web app manifest in the head of index.html.
    • View the manifest on Chrome DevTools > Application > Manifest. You may need to clear the cache then reload to see it.
    • Add iOS meta tags & icons. Safari on iOS doesn't support the web app manifest. Add traditional meta tags to the head of index.html file:
      ios meta tags
  4. Run an audit. Notice what tests are now passed.
  5. To fix a few more errors in the audit:
    • "Document does not have a meta description": detailed descriptions can improve your search results in Google. In the head of index.html add a meta tag with the attributes name="description" content="A sample weather app".
    • "Does not set an address-bar theme color": set the browser's address bar color to match your theme design to make it look seamless with the browser. In the head of index.html add a meta tag with the attributes name="theme-color" content="#2F3BA2"
    • "Does not redirect HTTP traffic to HTTPS": Add this code const redirectToHTTPS = require('express-http-to-https').redirectToHTTPS; to the top of server.js with the other required elements. Add the following code to the top of init():
  6. Run an audit. Notice what tests are now passed.
Repeat the steps above for your own app. Get an appropriate icon that does not break copyrights. You will need to add mofify your manifest to access the new icons. According to this github discussion on icon size coverage, the only sizes that are needed are 192x192 (for chrome), and 512x512 (for the Chrome Dev Tools Audit).

**Note: on glitch, if you upload images, they go into "assets" and you must use absolute references to access the images.

A Service worker is a script that your browser runs in the background from a web page. It allows you to support offline experiences, and add features like push notifications and background sync. With service workers you can cache the app shell and data for your app, so that it's available even when the network isn't.

There are some issues with service workers:
  • Not all browsers support service workers, for an up to date list go to Jake Archibald's Is Service Worker Ready?
  • they are only available on pages accessed via https, which is why we use for this course.

For more on service workers read Using Service Workers and The Service Worker Lifecycle. This tutorial is based on Google Code Labs.

We will be using it in this section to provide the user with a simple offline page of our own, instead of Chrome's dinosaur game.

What to do:
  1. Register the service worker. Create public/addserviceworker.jsand put this code in:
  2. Now include addserviceworker.js at the bottom of index.html.
  3. Precache an offline page.
    • Create offline.html with the following code: offline.html
    • Create public/service-worker.js
    • In service-worker.js add offline.html to FILES_TO_CACHE:
    • In service-worker.js add an install event to tell the service worker to pre-cache the offline page:
      install event
  4. Open Chrome DevTools and go to the Service Workers pane on the Application panel. You should see your service worker registered. Next to the Status label, there's a number. Keep an eye on that number, it's an easy way to tell if your service worker has been updated.
  5. Clean up old offline files.
    • To clean up old data in the cache, add an activate event to the page. For this to work, you must increment the CACHE_NAME variable in the service worker.
      increment cache
    • Now add the activate code to service-worker.js:
      activate event
    • Now refresh the app with Chrome Dev Tools open to the Service Workers pane. You will see the new service worker installed and the status number incremented.
  6. Handle failed network requests: To handle fetch requests, if a network request fails, the service work will return the offline page.
    Network fallback to cache
    • Add this code to service-worker.js
      Fetch event
    • Now refresh the app with Chrome Dev Tools open to the Service Workers pane. You will see the new service worker installed and the status number incremented.
    • Go to the Cache Storage pane on the Application panel of DevTools. Right-click Cache Storage, pick Refresh Caches, and expand the section. You should see the name of your static cache listed on the left-hand side. Click on the cache name to see all of the files that are cached.
  7. Test offline mode. Go back to the Service Workers pane in the Application panel of DevTools and check the Offline checkbox. After checking it, you should see a little yellow warning icon next to the Network panel tab. This icon indicates that you're offline.
  8. Debugging tips for service workers:
    • If your changes to the service worker don't seem to be updating in the browser, clear all saved data (localStorage, indexedDB data, cached files) and remove any service workers, by using the Clear storage pane in the Application panel of DevTools.
    • Once a service worker has been unregistered, it may remain listed until its containing browser window is closed.
    • If multiple windows to your app are open, a new service worker will not take effect until all windows have been reloaded and updated to the latest service worker.
    • Unregistering a service worker does not clear the cache.
    • If a service worker exists and a new service worker is registered, the new service worker won't take control until the page is reloaded, unless you take immediate control.
  9. Uncheck the Offline checkbox and run another audit. It should now pass the tests "Current page responds with a 200 when offline", "start_url responds with a 200 when offline", and "Registers a service worker that controls page and start_url."
Repeat the steps above for your own app. Run an audit and make sure all the PWA criteria are met. Test your app offline and ensure your offline.html loads.

Users expect apps on their phones to work even without an internet connection. This should also be true for progressive web apps. Designing for offline first can improve the performance of your app by reducing the number of its network requests. By precaching resources that will likely be needed, much of your app can be served from local storage instead of the network and this will make is significantly faster. This tutorial is based on Google Code Labs.

What to do:
  1. We are going to cache our static resources using a cache-first approach. This means our app will load initially from cache, but immediately update it from the network if anything has changed. This means the user will get data presented to them much faster, and if it's out of date, it will get new data loaded as soon as the network responds.

    Add the following code to client.js
  2. Now modify updateData() in client.js so that it makes two calls, one to getForecastFromNetwork() to get the forecast from the network, and one to getForecastFromCache() to get the latest cached forecast. The new code is highlighted:
    Update Data
  3. To ensure the app is displaying the latest data, make sure the following code from renderForecast() is uncommented:
    Last Update
  4. In the service worker, add a DATA_CACHE_NAME so that you can separate the application's data from the app shell.
    data cache
    Increment CACHE_NAME.
  5. In order for the app to work offline, precache all of the resources it needs. Update the FILES_TO_CACHE array with the list of files:
    Files to Cache
  6. Note that offline.html is no longer needed because the app now has all the necessary resources it needs to work offline, and won't ever show the offline page again.
  7. Increment the CACHE_NAME.
  8. Update the activate event handler. To ensure the activate event doesn't accidentally delete the data, in the activate event of service-worker.js, replace if (key !== CACHE_NAME) { with:
    if (key !== CACHE_NAME && key !== DATA_CACHE_NAME) {
  9. Update the fetch event handler. Modify the service worker to intercept requests to the weather API and store the responses in the cache by replacing the fetch event handler with the following code:
    The code intercepts the request and checks if it is for a weather forecast. If it is, use fetch to make the request. Once the response is returned, open the cache, clone the response, store it in the cache, and return the response to the original requestor.

    The evt.request.mode !== 'navigate' check is removed because we want the service worker to now handle all requests (including images, scripts, CSS files, etc), not just navigations. If we left that check in, only the HTML would be served from the service worker cache. Everything else would be requested from the network.
  10. The app should be completely offline-functional now. Refresh the page to ensure that you've got the latest service worker installed. Then save a couple of cities and press the refresh button on the app to get fresh weather data.
  11. In Chrome Dev Tools, go to Application > Cache Storage. Expand the section and you should see the name of your static cache and data cache listed on the left-hand side. Open the static cache to see all the cached static files. Open the data cache will to see the data stored for each city.
  12. Switch to the Service Workers pane, and check the Offline checkbox. Reload the page. It should retain it's data rather than giving you offline.html or Chrome's dinosaur game.
  13. Run the audit again.

If after completing all these steps, your Weather App does not work offline, clone this github repository:

How should your app act when the user is offline? What data and files must be cached for it to work? Write the code to cache all static files, and relevant data. Test your app offline.
  • No data should be cached twice.
  • No error messages should show on the browser viewport.
  • Enough API data should be cached so that there is limited functionality.
  • It looks and feels like the app it's supposed to be
Read the following articles:
  • What Makes a Great Mobile App?
  • 3 Rules of App Design
  • On a sheet of paper, make list of 3 things you could add/modify in your app to make it better. Hand it into Ms. Wear's Wire Inbox.
    How to tell if your app is offline:
    // check if app has connection to the internet
    function check() {
      isOnline = navigator.onLine;
      // show JSON if online, message if offline
      if(isOnline == true){
      } else {
        document.getElementById("someID").innerHTML = "You are offline";
      }// else
    } // check

    This tutorial is based on Google Code Labs.

    When installed, Progressive Web Apps look and behave like other installed apps. In order to be installable, they must meet the following criteria:

  • be served over https
  • register a service worker that controls the page and start_url
  • use a manifest that meets installability requirements
  • You can run an audit to see if your app meets these requirements. The Weather App should already meet these requirements.

    What to do
    1. Bypass the service worker: In Chrome DevTools go Application > Service Workers and check the box "Bypass for Network". Requests will bypass the service workers for this part of the development and save us having to update the service worker in the browser.
    2. Add an install button to index.html. You should already have the css and image for this button.
    3. Add install.js: Create public/install.js, and add the following code:
      Install.js code
    4. Add install.js to index.html:
      add install to index

      and add install.js to FILES_TO_CACHE in service-worker.js:
    5. If certain criteria are met by your app, Chrome will initiate a beforeinstallprompt event that you can use to prompt the user to install the app. Add this function to install.js to listen for the beforeinstallprompt event:
    6. Save the event and show the install button: Add the following function to install.js to save the beforeinstallprompt so we can later unhide the install button and prompt the user:
    7. Show the prompt, hide the install button, and record the user's response: When the user clicks the install button, call .prompt() on the saved beforeinstallprompt event. Since it can only be called once on each saved event, also hide the install button. Calling .prompt() will show a modal dialog, and ask the user to add your app to their homescreen. There is a property of the beforeinstallprompt called userChoice that contains the outcome of the user's response to the prompt. Add the following function to install.js
    8. Log all install events: Users can install your app through methods other than the install button. In Chrome, they can use the 3 dot menu. To record all of these events, add an event listener for the appinstalled event to install.js:
      and add the following function to install.js
    9. Increment CACHE_NAME in service-worker.js since files that are already cached have been modified.
    10. Test it.
      • In Chrome DevTools, go to Application > Clear Site Data. Clear away everything.
      • If you've already installed the app, uninstall it, otherwise the install icon won't show up.
      • Verify the install button shows up. Try this on a desktop and your phone.
        1. Open the app's url in a new Chrome tab
        2. Open Chrome's three-dot menu (next to the address bar) and ensure you see "Install Weather..." in the menu. This is what is looks like on my version of the app
        3. Refresh the weather data using the refresh button in the upper right corner of the app to ensure we meet the user engagement heuristics (this means your user must interact with the site before it can ask them to install the app). Verify that the install icon is visible in the app header. This is what is looks like on my version of the app (the CSS needs some work)
      • Verify the install button works.
        1. Open a new tab in Chrome and go to your web app url.
        2. If you are on a desktop, open Chrome DevTools open the Console panel.
          1. Click the install button on the app. Verify the install button disappears, the modal dialog box is shown.
          2. Click Cancel. Verify "User dismissed the A2HS prompt" is shown in the console. Verify the install button reappears.
          3. Click the install button again, then click the install button in the modal dialog. Verify "User accepted the A2HS prompt" is shown in the console, "Weather App was installed" is shown in the console, and that the Weather app is added to the place where you'd typically find apps. On my computer, it appears on the desktop:
            desktop icon
        3. Launch the Weather App from it's new icon. Verify the app opens as a standalone app, either in an app window on desktop, or full screen on mobile. Note: the Weather App should appear with a yellow background indicating it was launched from in standalone mode. You can modify this in the CSS.
      • On Mac and Windows, PWAs may be uninstalled through Chrome:
        1. In a new browser tab, open chrome://apps.
        2. Right click (alt-click) on the Weather PWA.
        3. Click Remove from Chrome...
        4. You can also open the installed PWA, click the the three-dot context menu in the upper right corner, and choose "Uninstall Weather PWA..."
    Complete the steps from above part 4 to your own app to make it installable. Note: if you want to use install.svg, since it is a text file (svg is text), simply add it to your glitch files and copy and paste the svg code from the weather app into it.
  • Do one of Blender 2.7 OR work on learn touch typing at OR start a Udemy Free Course. Show me what you've learned in 2.5 hours for completion credit!
  • For part of your completion credit: Please complete the Web Dev Course Evaluation