Progressive Web Apps Training https://developers.google.com/web/ilt/pwa/ Setting Up the Labs https://developers.google.com/web/ilt/pwa/setting-up-the-labs git clone https://github.com/google-developer-training/pwa-training-labs.git Web Server[s] :: Chrome 'Web Server' app OR Node.js 'http-server' module # "Web Server for Chrome" app [localhost:8887] # [npm install] http-server -g [localhost:8080] https://www.npmjs.com/package/http-server Lab: Scripting the Service Worker https://developers.google.com/web/ilt/pwa/lab-scripting-the-service-worker Install Event SUPPORT @ Chrome/Firefox https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent Lab: Fetch API SUPPORT @ Chrome/Edge/Firefox/Safari https://developers.google.com/web/ilt/pwa/lab-fetch-api#1_get_set_up Fetch API [replaces XMLHttpRequest] SUPPORT @ Chrome/Edge/Firefox/Opera/Safari [not really, i.e., 'response.ok' NOT @ Safari] https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#Browser_compatibility Response ... SUPPORT @ NONE if mobile ??? https://developer.mozilla.org/en-US/docs/Web/API/Response#Browser_compatibility Javascript Design Patterns https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript Qunit [JS Unit Test framework] https://qunitjs.com/ Learning Javascript Design Patterns https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript Blob/File object :: URL.createObjectURL(responseAsBlob) [WIDELY SUPPORTED] https://developer.mozilla.org/en-US/docs/Web/API/Blob https://developer.mozilla.org/en-US/docs/Web/API/Filehttps://developer.mozilla.org/en-US/docs/Using_files_from_web_applications #Example_Using_object_URLs_to_display_images Lab: Caching Files with Service Worker https://developers.google.com/web/ilt/pwa/lab-caching-files-with-service-worker Application-managed caches per Cache API; orthogonal to Browser-managed caches which are handled per browser. Browser-managed caches are NOT available offline. NOTE: Cache-API available @ 'window' object, so service worker NOT required; though designed as part of Service Worker spec. SUPPORT @ Chrome/Firefox Caching Files with Service Worker [Concepts] https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker Cache Interface SUPPORT @ Chrome/Android/Firefox https://developer.mozilla.org/en-US/docs/Web/API/Cache#Browser_compatibility Serve Files from Cache [INTERCEPTs NETWORK REQUESTS] CLONE; reading responses https://jakearchibald.com/2014/reading-responses/ Simulate Offline https://developers.google.com/web/ilt/pwa/tools-for-pwa-developers#offline The Offline Cookbook https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/ STRATEGY: 'Stale-while-revalidate' https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#stale-while-revalidate STRATEGY: 'Cache falling back to network' https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-falling-back-to-network Lab: Promises https://developers.google.com/web/ilt/pwa/lab-promises .then(function-called-@-RESOLVED, function-called-@-REJECTED) @ .then(func1, func2), func1 OR func2 will be called, never both. @ .then(func1).catch(func2), both will be called if func1 rejects, as they're separate steps in the chain. functions on an ARRAY of PROMISES .all() resolves if all of the promises passed into it resolve .race() settles [resolves] on first resolved promise passed to it Working with Promises https://developers.google.com/web/ilt/pwa/working-with-promises JavaScript Promises: an Introduction [load a story, chapter by chapter] getJSON('story.json').then(function(story) { addHtmlToPage(story.heading); ... https://developers.google.com/web/fundamentals/getting-started/primers/promises Promise Fates & States [no distinction even within their own abstractions;] https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md Lab: IndexedDB https://developers.google.com/web/ilt/pwa/lab-indexeddb Working with IndexedDB https://developers.google.com/web/ilt/pwa/working-with-indexeddb idb [IndexedDB, but with promises] [Library:2KB] [jakearchibald/idb] https://github.com/jakearchibald/idb [GitHub] https://www.npmjs.com/package/idb [Node.js] IndexedDB API [MDN] https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API .createObjectStore() https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/createObjectStore Lab: Workbox [SUCCESSOR to sw-precache + sw-toolbox] [2017-09] https://developers.google.com/web/ilt/pwa/lab-workbox Lab: sw-precache and sw-toolbox [node-based] applications https://developers.google.com/web/ilt/pwa/lab-sw-precache-and-sw-toolbox # 4. Creating the service worker with sw-precache and gulp npm install --global gulp-cli cd ... /app # go to project dir npm init # creates 'package.json'; info about the project and its dependencies. npm install gulp --save-dev # download required Gulp dependencies # creates ... and subdirs [~3MB]; each dir has one or more: .js, .json, .md ./app/node_modules # install the sw-precache and sw-toolbox pkgs, and path pkg npm install --save-dev path sw-precache sw-toolbox # run task: generate service-worker.js; after setting config @ gulpfile.js gulp service-worker # 5. Creating routes with sw-toolbox # 6. Optional: Creating the service worker in the command line https://github.com/GoogleChrome/sw-precache#command-line-interface sw-precache and sw-toolbox are two packages created by Google to automate the creation of service workers, and to make the creation of custom caching routes easier. https://developers.google.com/web/ilt/pwa/using-sw-precache-and-sw-toolbox Gulp - Front-end Build Tool [Task Runners]; Grunt was predecessor; others: Broccoli.js, Brunch, Webpack; Node/npm do much, and the [other] tools too. Tutorial: https://www.sitepoint.com/introduction-gulp-js/ Making Sense of Front-end Build Tools https://medium.freecodecamp.com/making-sense-of-front-end-build-tools-3a1b3a87043b Lab: Responsive Design https://developers.google.com/web/ilt/pwa/lab-responsive-design # /index.html # /styles/main.css @media screen and (max-width: 48rem) { .container .col { width: 95%; } } # NOTHING WORKED UNTIL # 5.4 ... /* DONE :: TODO 5.4 - use media query with Flexbox */ Flexible boxes, or flexbox, is a new layout mode in CSS3. https://www.w3schools.com/css/css3_flexbox.asp # 6. Using Flexbox as a progressive enhancement As Flexbox is a relatively new technology, we should include fallbacks in our CSS. Modernizr is a feature detection tool that simplifies testing for Flexbox support. https://modernizr.com/download?setclasses # /index.html [4KB] ... which adds ".[no-]flexbox" classes to elements per browser flex-box support So, can then prepend .[no-]flexbox class to each rule @ css file. Lab: Responsive Images https://developers.google.com/web/ilt/pwa/lab-responsive-images browser chooses, from 'srcset' listed images when fetching image, per: viewport dimensions, image size relative to viewport, device pixel density, and source file dimensions. Browser downloads larger images as viewport grows, without page refresh! SIZE PER VIEWPORT WIDTH [%vw]; @ html OR css: [html] img#id {max-width: 50vw;} [css] CHANGE %vw per viewport width, DYNAMICALLY, using MEDIA QUERIES; e.g., display img @ 50% if viewport larger than 700px, but at 90% if viewport smaller than 700px ... @media screen and (max-width: 700px) { [css] img#id { max-width: 90vw; width: 90vw; } } [html] # 6. Optional: Use HTML5 PICTURE and SOURCE elements https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source
Horses in Hawaii
Horses in Hawaii
Intro to PWA Architectures https://developers.google.com/web/ilt/pwa/introduction-to-progressive-web-app-architectures Notes: In the future, consider a server-side render (SSR) of UI with Streams for body content model (even better). See https://jakearchibald.com/2016/streams-ftw/ to learn more. If you are building a PWA using Polymer leveraging this pattern, then it might be worth exploring SSR of content in the Light DOM STREAMs !!! >>> ReadableStream [Web API] :: .getReader() 2016 - the year of web streams [jakearchibald.com] // https://jakearchibald.com/2016/streams-ftw ReadableStream [Web API] :: .getReader() https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#Browser_compatibility Lab: Integrating Web Push https://developers.google.com/web/ilt/pwa/lab-integrating-web-push npm install # reads/runs-tasks per './package.json' file; installs dependencies etc. npm install web-push -g # 2. Using the Notification API Intro to Push Notifications [analogous to native 'Push Messaging'] https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications#how_web_push_works ServiceWorkerRegistration https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration .showNotification() https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification Notifications API https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API # 3. Using the Push API *** SKIP DOWN TO 4.2; VAPID Protocol [NOT Google/Firebase labyrinth-of-bullshit] Push API https://developer.mozilla.org/en-US/docs/Web/API/Push_API Push Event [Interface of Push API] https://developer.mozilla.org/en-US/docs/Web/API/PushEvent Send SIMULATED push notifications https://developers.google.com/web/ilt/pwa/tools-for-pwa-developers#push ROUTE PUSH MESSAGEs Firebase account/console https://console.firebase.google.com/?pli=1 Chrome uses Firebase Cloud Messaging (FCM) to route its push messages. All push messages are sent to FCM, and then FCM passes them to the correct client. [FCM has replaced Google Cloud Messaging (GCM). Some of the code to push messages to Chrome still contains references to GCM. These references are correct and work for both GCM and FCM.] OR use VAPID Protocol instead of FCM [avoid creating a Firebase account] VAPID Protocol https://developers.google.com/web/ilt/pwa/lab-integrating-web-push#vapid https://tools.ietf.org/html/draft-thomson-webpush-vapid-02 Use the VAPID protocol to identify the app for the push service. This eliminates the need for a Firebase account. # 4.2 Subscribe with the public key [VAPID Protocol] SUBSCRIPTION_OBJECT obtained from 'Enable Push Messaging' button Intro to the Payment Request API [under Develepment] https://developers.google.com/web/ilt/pwa/introduction-to-the-payment-request-api Introducing the Payment Request API https://developers.google.com/web/fundamentals/discovery-and-monetization/payment-request/ Lab: Integrating Analytics https://developers.google.com/web/ilt/pwa/lab-integrating-analytics Integrating Analytics https://developers.google.com/web/ilt/pwa/integrating-analytics Google Analytics Reporting API https://developers.google.com/analytics/devguides/reporting/core/v4/ Lab: Gulp Setup https://developers.google.com/web/ilt/pwa/lab-gulp-setup Introduction to Gulp https://developers.google.com/web/ilt/pwa/introduction-to-gulp