Enonic Workshop

in

2018 (#TheYearOfPWA)

NATIVE VS WEB

PWA

WTF IS            ?

PROGRESSIVE WEB APPLICATIONS

PWA

SERVICE WORKER

SERVICE WORKER IS...

if (containsDataUrl(e.request.url) || responseUpdate) {
    let url = responseUpdate ? e.request.url.replace("?update=true", "") : e.request.url;
    
    e.respondWith(
      caches.open(responseUpdate ? cacheName : dataCacheName).then(function(cache) {
          consoleLog("Fetching data url " + url);
          return fetch(e.request)
              .then(function (response) {
                  cache.put(url, response.clone());
                  return response;
              })
              .catch(function (ex) {
                  consoleLog('Network is down. Trying to serve from cache...');
                  return cache.match(e.request, {
                      ignoreVary: true
                  })
                  .then(function (response) {
                      consoleLog((response ? 'Serving from cache' : 'No cached response found') + ': ' + e.request.url);
    
                      return response || getFallbackPage(e.request.url);
                  });
              });
      })
    );
  }
  else {
      e.respondWith(
          caches.match(e.request, {
              ignoreVary: true
          })
          .then(function (response) {
              consoleLog((response ? 'Serving from cache' : 'Requesting from the server') + ': ' + e.request.url);

              return response || fetch(e.request);
          })
      );
  }

COMPLICATED

ENONIC PWA STARTER

ENONIC PWA STARTER

DOES ALL THE DIRTY JOB FOR YOU!

ENONIC PWA STARTER

  • Generates and registers Service Worker

  • Implements Web Manifest

  • Bundles JS files and stylesheets

  • Precaches all assets

  • Implements fallback page

  • Routes requests

  • Passes all audits on Lighthouse with 100 score

ENONIC PWA STARTER

(Checklist before you start)

  • Download and unpack Enonic XP distro
  • Use IDE of your choice
  • Gradle, NPM
export XP_INSTALL=/Users/ase/Downloads/enonic-xp-6.13.1-SNAPSHOT 
export XP_HOME=/Users/ase/Downloads/enonic-xp-6.13.1-SNAPSHOT/home
  • Set XP_INSTALL and XP_HOME environment variables
  • Start XP
$XP_INSTALL/bin/server.sh

OSX

$XP_INSTALL/bin/server.bat

WIN

set XP_INSTALL=/Users/ase/Downloads/enonic-xp-6.13.1-SNAPSHOT 
set XP_HOME=/Users/ase/Downloads/enonic-xp-6.13.1-SNAPSHOT/home

OSX

WIN

ENONIC PWA STARTER

You need

"Started Enonic XP in X seconds..."

ENONIC PWA STARTER

(Set up your project)

  • Create a new empty folder for your future PWA app
  • From that folder run:
$XP_INSTALL/toolbox/toolbox.sh init-project -n com.company.myapp -r starter-pwa

NB! Feel free to change com.company.myapp. It's the myapp part that is your app name.

$XP_INSTALL/toolbox/toolbox.bat init-project -n com.company.myapp -r starter-pwa
  • Build the project:
./gradlew deploy
gradlew deploy

OSX

WIN

OSX

WIN

  • myapp-1.0.0-SNAPSHOT.jar should appear in $XP_HOME/deploy

ENONIC PWA STARTER

(If you are lost...)

Scroll down to "Installation" section in README.MD

ENONIC PWA STARTER

ENONIC PWA STARTER

ENONIC PWA STARTER

(Project Structure)

build.gradle
gradle.properties
settings.gradle
  • Add dependencies
  • Change distro name
  • Add build tasks

Files:

Purpose:

Files used by the Gradle build

Modify to:

ENONIC PWA STARTER

(Project Structure)

webpack.config.js
  • Create additional bundles
  • Include additional plugins
  • Include additional assets in bundles or SW
  • Change location of bundles or SW

File:

Purpose:

  • Bundles client-side assets (.js, .less) by unwinding a chain of dependencies (via 'require')
  • Generates a Service Worker file

Modify to:

ENONIC PWA STARTER

(Project Structure)

main.js
  • Add routes for new templates
  • Modify arguments passed to the templates
  • Include additional assets in bundles or SW
  • Change location of bundles or SW

File:

Purpose:

  • Main server-side entry point for your app
  • Controls routing to site pages and sw.js
  • Controller for rendering of templates (/pages/*.html)

Modify to:

ENONIC PWA STARTER

(Project Structure)

/pages/main.html
/pages/about.html
/pages/contact.html
  • Change site layout or content of the pages

File(s):

Purpose:

  • Templates for the site pages rendered from main.js

  • Placeholder {{{styles}}} will be replaced by inline styles from pages/styles.html

  • Placeholder {{{serviceWorker}}} will be replaced by SW registration code from pages/sw.html

Modify to:

ENONIC PWA STARTER

(Project Structure)

/pages/styles.html

File(s):

Purpose:

Modify to:

These are inline styles that will be TEMPORARILY injected into every page (replace {{{styles}}} placeholder) to speed up rendering before the bundle.css is loaded by the browser

Should contain the very minimum of styling required for a user to not notice transition when the bundle.css file is loaded

ENONIC PWA STARTER

(Project Structure)

/pages/sw.html

File(s):

Purpose:

Modify to:

  • Contains the code fragment that registers Service Worker. Will replace {{{serviceWorker}}} placeholder on every site page.
  • Sets up events to notify about new SW version
  • Dynamically injects references to CSS files and removes inline styles once the external CSS files are loaded
  • Set up additional SW events
  • Inject additional stylesheets

ENONIC PWA STARTER

(Project Structure)

/lib/helper.js

File(s):

Purpose:

Modify to:

  • Add methods that should be available to other server-side classes
  • Contains helper methods used by server-side code

ENONIC PWA STARTER

(Project Structure)

/lib/sw-controller.js

File(s):

Purpose:

Modify to:

  • Pass parameters to the SW template file 
  • Renderer of the Service Worker template file (sw-dev.js)

ENONIC PWA STARTER

(Project Structure)

/assets/browserconfig.xml
/assets/manifest.json

File(s):

Purpose:

Modify to:

  • Web Manifest files

ENONIC PWA STARTER

(Project Structure)

/assets/precache/**/*

File(s):

Purpose:

Modify to:

  • Any new assets under /precache will be automatically precached by SW according to pattern specified in webpack.config.js

  • Assets (3rd-party CSS, JS libs, icons)

ENONIC PWA STARTER

(Project Structure)

/assets/js/sw-dev.js

File(s):

Purpose:

Modify to:

  • Change your Service Worker logic
  • Template for the Service Worker file

ENONIC PWA STARTER

(Project Structure)

/assets/js/main.js

File(s):

Purpose:

Modify to:

  • Add client-side events to controls
  • Add more dependencies (via 'require')
  • Main entry point for the client-side code
  • First link of the dependency chain that Webpack will use while bundling the app 

ENONIC PWA STARTER

(Project Structure)

/assets/css/styles.less

File(s):

Purpose:

Modify to:

  • Change default styling
  • Add new LESS dependencies
  • NB! Remember to update injected inline styles in styles.html if you do radical styling changes
  • Main LESS file for the app
  • Bundles into bundle.css thanks to 'require' in the main.js

ENONIC PWA STARTER

(Main Files)

  • resources/assets/js/sw-dev.js
  • resources/assets/js/main.js
  • resources/main.js

The main server-side entry point. Controls routing and renders the HTML pages

The main client-side entry point. Starts the chain of Webpack dependencies.

Template for the Service Worker. Add your custom logic here.

ENONIC PWA STARTER

USE CASES

ENONIC PWA STARTER

1. Add jQuery (or any other NPM module)

npm install jquery

1) Install jquery NPM module

2) require jquery from main.js and use it!

const $ = require('jquery');

$(document).ready(() => {
...
});

ENONIC PWA STARTER

2. Add a new *.js file 

1) Add the file to assets/js

2) require it from main.js:

require('new');
...

It will be automatically bundled into bundle.js by Webpack

ENONIC PWA STARTER

3. Precache a new asset 

(automatic option)

1) Add the asset file anywhere under /assets/precache/

2) It will be automatically precached by Workbox-generated Service Worker

ENONIC PWA STARTER

4. Precache a new asset 

(manual option)

1) If the asset is not under /assets/precache/, you will have to specify that it must be cached (sw-dev.js)

2) It will be precached by Workbox-generated Service Worker

ENONIC PWA STARTER

Runtime caching

ENONIC PWA STARTER

Possible caching strategies:

  • workbox.strategies.staleWhileRevalidate()
  • workbox.strategies.networkFirst()
  • workbox.strategies.cacheFirst()
  • workbox.strategies.networkOnly()
  • workbox.strategies.cacheOnly()

ENONIC PWA STARTER

Set up routes in Service Worker (sw-dev.js):

workboxSW.router.setDefaultHandler({
    handler: workboxSW.strategies.cacheFirst()
});

workboxSW.router.registerRoute(
    '{{baseUrl}}/about',
    workboxSW.strategies.networkFirst()
);

workboxSW.router.registerRoute(
    'https://swapi.co/api/people/?format=json',
    workboxSW.strategies.staleWhileRevaliate()
);

// Advanced handling

self.addEventListener('fetch', (event) => {
  if (event.request.url.indexOf('/image') > -1) {
    const staleWhileRevalidate = new workbox.strategies.StaleWhileRevalidate();
    event.respondWith(staleWhileRevalidate.handle({event}));
  }
});

ENONIC PWA STARTER

If you want the "classic" promise-based Service Worker logic, just add it here

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('mysite-dynamic').then(function(cache) {
      return cache.match(event.request).then(function (response) {
        return response || fetch(event.request).then(function(response) {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

TEAMS

Team A

ARO

VBR

JSI

BHJ

Team B

GRI

ASL

BWE

DAP

Team C

RMY

MTA

RFO

ESU

Team D

PMI

SIG

CWE

ENO

ASSIGNMENTS

Assignment 1

Come up with a name for your team!

Rules:

  • use only letters from your combined initials
  • each letter can be reused
  • any number of words
  • bad words are welcome

 

For example, TSI + MER + SIW + KLA = SWEET TEAM 

Assignment 2

Decide what kind of PWA you're going to build with the PWA starter

Ideally it should be something useful...

...but useless and funny is also good :-)

Some suggestions...

Expand the PWA starter with cool browser APIs

  • Push Notifications: use lib-notifications

Expand the PWA starter with cool browser APIs

  • Battery Status: use some cool battery icon
  • GeoLocation: fetch coordinates, draw the map, cache it
  • Any other API of your choice... (but make it look good!)

Application list

GET: https://market.enonic.com/applications?xpVersion=6.13.0&ids=[]

Accept: application/json

Content-Type: application/json

1. Cache request to the application list

2. Cache app icons

3. Cache styles and fonts

Turn XP admin dashboard into a PWA

https://github.com/xp-apps/modules/app-main

Turn the main page of enonic.com into a PWA

https://github.com/enonic/enonic.com

Assignment 3

Init your future PWA via Toolbox

 

Check “Installation” section in https://github.com/enonic/starter-pwa

Assignment 4

Find a cool name for your app

and find all the places where it's supposed to be replaced

Assignment 5

When your app is finished, verify it with Lighthouse

Good Luck!

Kickoff Workshop in Berlin

By Alan Semenov

Kickoff Workshop in Berlin

  • 1,252