Coding

Building Our First PWA | Example Project

  • 00:00:01 welcome to this video where I want to
  • 00:00:03 build a basic progressive web app with
  • 00:00:05 you now I already do have a video about
  • 00:00:08 progressive web apps on my channel you
  • 00:00:10 can find a link in the video description
  • 00:00:11 of course and this our video it's
  • 00:00:14 basically taken from my complete
  • 00:00:16 progressive web of course I host an
  • 00:00:17 udemy of course you can also find a link
  • 00:00:19 to Disney video description now in this
  • 00:00:22 video here I want to build a progressive
  • 00:00:24 weather with you which works offline and
  • 00:00:27 which we can install on the device home
  • 00:00:29 screen of an Android device so let's do
  • 00:00:32 that let's dive into that and let's
  • 00:00:34 learn what it takes to create a basic
  • 00:00:36 progressive web app
  • 00:00:40 so in the video description you can find
  • 00:00:43 a link to a starting project which I
  • 00:00:45 already opened in webstorm it's a very
  • 00:00:48 basic project and as you can see in the
  • 00:00:50 readme of that file you'll need no js'
  • 00:00:52 to run this development server this
  • 00:00:55 project uses and you'll also need to
  • 00:00:57 install the dependencies though their
  • 00:00:59 dependency is really just as one
  • 00:01:01 dependency here at HTTP server and then
  • 00:01:04 we have to start command which spins up
  • 00:01:06 the HTTP server so let's do that let's
  • 00:01:08 first of run an NPM install to install
  • 00:01:11 that server and once we did this we can
  • 00:01:13 start it with NPM start and of course
  • 00:01:16 keep that process running because we
  • 00:01:17 want to keep our development server
  • 00:01:19 running you'll then find the addresses
  • 00:01:21 under which you can visit the project in
  • 00:01:23 the console but you can also simply
  • 00:01:25 wizard localhost 8080 1 now this page is
  • 00:01:30 a very simple web application it's not a
  • 00:01:32 progressive web app at all and all we
  • 00:01:34 can do right now is we have this huge
  • 00:01:36 card here which you can click and when
  • 00:01:38 we click it then the text down here
  • 00:01:40 changes with a little animation and we
  • 00:01:42 can go back and forth between the
  • 00:01:44 different content so obviously the
  • 00:01:46 application here might not blow your
  • 00:01:48 minds but the cool thing is that it's a
  • 00:01:51 nice application where we can add
  • 00:01:52 progressive features or features of
  • 00:01:54 progressive web apps to make it a
  • 00:01:56 progressive web app I strongly recommend
  • 00:01:59 checking out that other video I
  • 00:02:00 mentioned which I took from my complete
  • 00:02:02 guide to get you into the basics of
  • 00:02:05 progressive weather app so that you
  • 00:02:06 learn why you might want to build them
  • 00:02:07 and what makes a progressive web apps
  • 00:02:09 now with that let's turn this
  • 00:02:12 application into a progressive web app
  • 00:02:14 by first of all adding a manifest file a
  • 00:02:18 manifest file is a file which is read by
  • 00:02:21 the browser's by browsers supporting it
  • 00:02:23 at least and this file then allows the
  • 00:02:26 browser to get some extra information
  • 00:02:28 about your page something like the icon
  • 00:02:31 it should use or for example the name
  • 00:02:33 description of the page things like
  • 00:02:36 these which allow the browser to display
  • 00:02:38 your page correctly and very important
  • 00:02:41 to install it on the home screen with
  • 00:02:44 your own icon and so on so that's the
  • 00:02:47 idea behind the manifest file in general
  • 00:02:50 though we need to understand which
  • 00:02:52 browsers do some
  • 00:02:53 word which progressive web app features
  • 00:02:55 let's have a look at that on the web app
  • 00:02:58 manifest page of the Mozilla developer
  • 00:03:00 Network you can not only find some
  • 00:03:03 information about how this file should
  • 00:03:04 be structured and which properties you
  • 00:03:06 can add I strongly recommend this
  • 00:03:08 article but of course I will also walk
  • 00:03:09 you through the most important
  • 00:03:10 properties in this video but you can
  • 00:03:12 also found if you scroll down you can
  • 00:03:15 also find some information about the
  • 00:03:17 browser support now what you see here
  • 00:03:20 browser compatibility that it's not
  • 00:03:22 supported at all that's not entirely
  • 00:03:24 true many features like installing it on
  • 00:03:27 the home screen simply doesn't work on
  • 00:03:28 desktop like that but if you check out
  • 00:03:31 mobile that's the more interesting part
  • 00:03:32 because that is what we want to add our
  • 00:03:35 application to the device screen and
  • 00:03:36 there you see how it gets how it is
  • 00:03:39 supported and support is pretty well on
  • 00:03:41 Android now iOS Safari the support is
  • 00:03:45 not there yet but Safari is also working
  • 00:03:49 on progressive web as we see some
  • 00:03:51 development there so chances are that
  • 00:03:53 this file will also be readable by
  • 00:03:55 Safari on iOS or other browsers on iOS
  • 00:03:58 in the future so for now let's focus on
  • 00:04:01 Chrome for Android and all the other
  • 00:04:03 Android browsers and then we see it's
  • 00:04:05 pretty good so this is the web app
  • 00:04:07 manifest and to use such a file we
  • 00:04:10 should add it to our project now the
  • 00:04:12 application is actually served from the
  • 00:04:15 public folder this is where all the
  • 00:04:17 source code of the web app you saw lives
  • 00:04:19 now if we have a look at it the river
  • 00:04:21 index.html file and then we have our
  • 00:04:24 source folder with the different asset
  • 00:04:26 scripts images and so on now important
  • 00:04:29 here I only got one HTML file I'm not
  • 00:04:32 creating a single page application ship
  • 00:04:34 though well it is only a single page so
  • 00:04:36 I guess technically it is one but I'm at
  • 00:04:38 least not using any framework I'm not
  • 00:04:40 using angular react or view here if you
  • 00:04:43 check out my JavaScript file it's a very
  • 00:04:45 simple file using vanilla JavaScript and
  • 00:04:47 this is important you can turn a single
  • 00:04:50 page application driven by react angular
  • 00:04:53 and so on into a progressive web app you
  • 00:04:56 can also turn any other application into
  • 00:04:58 a progressive weather also multi page
  • 00:05:01 applications and the course I mentioned
  • 00:05:03 at the beginning my udemy course
  • 00:05:05 actually uses a mult
  • 00:05:06 Paige application to show you how
  • 00:05:08 versatile this concept is and that you
  • 00:05:10 can apply to any web app that's really
  • 00:05:12 important to me that you understand this
  • 00:05:14 any web app so back to that manifesto
  • 00:05:18 chase have folded the right place to add
  • 00:05:21 it is right next or index.html file so
  • 00:05:23 there I'll create a new file and I'll
  • 00:05:25 name it manifest Jason it has to be
  • 00:05:28 adjacent file now with that added
  • 00:05:31 without any content in it yet I'll go to
  • 00:05:34 the index.html file and there at the end
  • 00:05:37 of the head section I'll now add a new
  • 00:05:39 link it won't be of type stylesheet
  • 00:05:43 though instead it should be relating to
  • 00:05:45 a manifest and the link should simply
  • 00:05:48 point to slash many faster Jason so to
  • 00:05:51 this manifest file once you did this we
  • 00:05:55 can start filling this file with life
  • 00:05:56 and since it's a JSON file we should of
  • 00:05:59 course write jason code in there so what
  • 00:06:02 goes into such a manifesto Jason fall
  • 00:06:05 first of all you can give your
  • 00:06:07 application a name like a basic
  • 00:06:10 progressive web app whatever you want
  • 00:06:13 this name will be used in some places
  • 00:06:15 for example on the splash screen which
  • 00:06:18 Android will automatically show you if
  • 00:06:20 you start your application after you
  • 00:06:23 installed it on the home screen however
  • 00:06:25 there are all the places like below the
  • 00:06:27 icon where this name is simply too long
  • 00:06:29 that's why there's also a short name
  • 00:06:32 property and this showed us the name
  • 00:06:34 indicate be a short name like basic PWA
  • 00:06:38 this will be used below the icon on your
  • 00:06:40 home screen and to make sure it's not
  • 00:06:42 getting cut off you should pick a short
  • 00:06:44 while string a short text here now
  • 00:06:47 beside that we also have a start URL
  • 00:06:50 because all lowercase by the way because
  • 00:06:54 if you think about your app being added
  • 00:06:57 to the home screen and the important
  • 00:06:59 part about this installation thing which
  • 00:07:01 I'll later show you is of course that
  • 00:07:03 all the time when I say install it's
  • 00:07:05 still a web app it's not a native
  • 00:07:09 Android app you're running then it is a
  • 00:07:11 web app in its core it's going to wizard
  • 00:07:13 your web page which gets served from
  • 00:07:15 your servers so this is why we have to
  • 00:07:17 specify a start URL here
  • 00:07:20 you could just say dot to simply use
  • 00:07:22 this folder where the manifesto Jason
  • 00:07:24 for lies in as a start URL which makes
  • 00:07:27 sense for me here because that's the
  • 00:07:28 public folder and that is our route web
  • 00:07:30 folder but you could of course also say
  • 00:07:32 slash index.html or whatever it is so
  • 00:07:36 I'll go back to dot though because I
  • 00:07:37 simply want to serve my root folder
  • 00:07:39 whenever the user taps this icon on the
  • 00:07:42 home screen now there's also another
  • 00:07:44 important property that's the display
  • 00:07:46 property here we can control how our
  • 00:07:49 progressive web app runs in the end if
  • 00:07:52 we open it if we open it from the home
  • 00:07:54 screen I mean does it should look like
  • 00:07:56 it's running the browser with the
  • 00:07:58 browser toolbar at the top or does it
  • 00:08:00 look like a real native app still again
  • 00:08:03 it will always be a web app but we can
  • 00:08:05 change the way it looks and to really
  • 00:08:07 create an immersive feeling we might
  • 00:08:10 want to pick standalone here our
  • 00:08:13 alternatives would be fullscreen or
  • 00:08:17 browser so here I'll pick standalone to
  • 00:08:21 really make it look like a standalone
  • 00:08:23 application and therefore reassembling
  • 00:08:26 this native app look we also have
  • 00:08:30 orientation now orientation allows us to
  • 00:08:33 control how the user should view our
  • 00:08:36 application now we can't rely on the
  • 00:08:38 browser and forcing this actually or the
  • 00:08:41 device but here we could say portrait to
  • 00:08:44 make sure that this app can only be
  • 00:08:46 viewed in portrait mode if started from
  • 00:08:48 the home screen so I'll add this here
  • 00:08:51 too and now the nice thing is the
  • 00:08:54 background color and this is again all
  • 00:08:56 lowercase here the background colors for
  • 00:09:00 example used on the splash screen which
  • 00:09:02 is created automatically which will be
  • 00:09:04 the background color and your app icon
  • 00:09:06 now I'll come back to the icon thing but
  • 00:09:09 that is for example reset the background
  • 00:09:11 color
  • 00:09:11 what the background color here is not
  • 00:09:13 it's the background color of your
  • 00:09:15 general page so it's not this white
  • 00:09:18 background here this is not controlled
  • 00:09:20 for the manifest and I'm really talking
  • 00:09:22 about the background during startup of
  • 00:09:24 the application for example so here why
  • 00:09:26 don't we pick some greyish color we also
  • 00:09:30 have a theme color and the theme color
  • 00:09:33 now for example Styles the toolbar
  • 00:09:35 already when your application runs in
  • 00:09:38 the browser the browser toolbar color
  • 00:09:40 should change but also especially if we
  • 00:09:43 started our app through tapping the icon
  • 00:09:45 and then for example we open the tasks
  • 00:09:48 which are on our mobile device we will
  • 00:09:50 see that our application runs as a
  • 00:09:52 separate task colored in our theme color
  • 00:09:54 so that is where we can see that now you
  • 00:09:57 can pick any color I'll simply pick a
  • 00:10:00 color from this image here so maybe this
  • 00:10:03 blue here which is the following hex
  • 00:10:06 code 5f AAA e5 and that again will be
  • 00:10:11 used in some places for example the task
  • 00:10:14 switcher now with that we can go to
  • 00:10:18 another important part the icons and
  • 00:10:20 this is I cans not I can and I can say
  • 00:10:24 is an array because you can specify
  • 00:10:26 multiple icons in different sizes
  • 00:10:28 basically each icon is defined as a
  • 00:10:31 JavaScript object here in this JSON file
  • 00:10:33 and then has free properties the source
  • 00:10:36 pointing to the I can file now in this
  • 00:10:39 project you are using you already will
  • 00:10:41 find this images folder and in there
  • 00:10:43 this icons folder where I prepared some
  • 00:10:45 icons for you and here we can simply
  • 00:10:47 point to them so we can say source
  • 00:10:50 images icons and then for example app I
  • 00:10:53 can – 96 by 96 dot PNG that is the path
  • 00:10:59 to the I can I wanna use we also have to
  • 00:11:03 explicitly set these sizes of that icon
  • 00:11:05 because we can probably guess that it's
  • 00:11:07 96 by 96 but of course we could have
  • 00:11:10 named this file anything we want so we
  • 00:11:12 clearly have to tell the browser what
  • 00:11:14 the size of that icon is and here it's
  • 00:11:16 96 by 96 and this is how we should
  • 00:11:18 specify this format this value here now
  • 00:11:21 why do we need to tell the browser the
  • 00:11:23 size of the icon because the browser
  • 00:11:25 should pick the right icon for the
  • 00:11:27 different devices where this application
  • 00:11:29 might run on and depending on the
  • 00:11:31 density of the screen and the resolution
  • 00:11:33 of the screen of the device it should
  • 00:11:34 pick a well-fitting icon the last
  • 00:11:37 property for each icon is the type and
  • 00:11:40 here this is image PNG and it should be
  • 00:11:43 a PNG image if you want to use it
  • 00:11:46 as a home screen icon as a splash screen
  • 00:11:48 icon theoretically other formats are
  • 00:11:51 supported to hurt you but to have an
  • 00:11:53 installable application where chrome
  • 00:11:55 actively prompts the user whether he
  • 00:11:58 wants to install it add a to the home
  • 00:12:00 screen or not you should set this at
  • 00:12:02 least this is the case right now
  • 00:12:04 now this is one icon but we got more I
  • 00:12:06 can store it so I'll specify them all
  • 00:12:09 the next one we'll check ft dimensions
  • 00:12:12 144 by 144 and this is actually an icon
  • 00:12:16 which you should always provide this
  • 00:12:18 dimension 144 by 144 this is an icon
  • 00:12:21 which is required so that chrome shows
  • 00:12:24 this do you want to install this app
  • 00:12:27 pop-up to the user basically 144 by 144
  • 00:12:30 has to be provided if you don't provide
  • 00:12:33 any other icons provide this size so the
  • 00:12:36 next icon I want to add here is of
  • 00:12:39 course the the next I can – that folder
  • 00:12:42 so 2 5 6 by 2 5 6 and then let's add the
  • 00:12:46 last icon this last I can here is pretty
  • 00:12:48 important for the splash screen display
  • 00:12:51 though it will work without it
  • 00:12:53 now this is a basic app manifest a basic
  • 00:12:57 manifest adjacent fall now with that
  • 00:12:59 let's save all of that and let's go back
  • 00:13:02 to this application let's reload it and
  • 00:13:04 let's open the developer tools now I'm
  • 00:13:06 using Chrome here and I strongly
  • 00:13:08 recommend using Chrome because they have
  • 00:13:10 awesome developer tools when it comes to
  • 00:13:12 debugging or working with progressive
  • 00:13:14 web apps there you can visit the
  • 00:13:16 application tab and let me increase this
  • 00:13:21 so there you can visit the application
  • 00:13:22 tab and there you'll find this manifest
  • 00:13:25 area if you click on it you should see
  • 00:13:28 the information the browser could get
  • 00:13:30 from the manifest you specified so the
  • 00:13:33 name the short name the color and all
  • 00:13:35 the icons you specified here so that's
  • 00:13:38 awesome this seems all to work fine now
  • 00:13:41 we could already manually add it to the
  • 00:13:43 home screen we could go to a mobile
  • 00:13:45 device an Android device simply open
  • 00:13:48 this application if it were to run on a
  • 00:13:50 server and then tap deep Add to Home
  • 00:13:52 screen I can manually D add to
  • 00:13:55 homescreen menu option we should then
  • 00:13:57 already use this icon ansan but
  • 00:14:00 Jerome won't actively prompt us to do
  • 00:14:02 that to install it however there are
  • 00:14:05 some criteria and a link to the criteria
  • 00:14:07 can be found in the video description
  • 00:14:09 which to find when Chrome will show you
  • 00:14:12 this actively so when it actively asks
  • 00:14:15 the user whether he wants to add the
  • 00:14:17 page the user is currently on QT a home
  • 00:14:19 screen or not now right now when I
  • 00:14:22 record this video the criteria are that
  • 00:14:24 you have a manifesto JSON file with 144
  • 00:14:28 by 144 PNG icon that you of course
  • 00:14:32 should specify a name and so on short
  • 00:14:34 name and that you also have a
  • 00:14:37 serviceworker
  • 00:14:38 we don't have dead yet that you also
  • 00:14:41 visited the page with a five-minute
  • 00:14:44 pause in between budget that you came
  • 00:14:46 back basically because you probably
  • 00:14:48 liked the page and that's important that
  • 00:14:51 your page has served over HTTP now
  • 00:14:54 during development localhost is actually
  • 00:14:56 an exception but you should serve it
  • 00:14:59 over HTTP because service workers
  • 00:15:01 require HTTPS and service workers are a
  • 00:15:04 requirement for the app manifest again
  • 00:15:06 localhost is the single exception that
  • 00:15:10 exists where you can also serve your
  • 00:15:12 progressive web app over localhost and
  • 00:15:14 see all the features of course that's
  • 00:15:15 not available when serving it on a real
  • 00:15:17 server so there make sure you're serving
  • 00:15:20 your page over HTTPS so what did we get
  • 00:15:23 the manifest let's now add a service
  • 00:15:26 worker and for that I'll add a
  • 00:15:29 JavaScript file because a service worker
  • 00:15:31 is just using javascript you could be
  • 00:15:33 inclined to add it in the JavaScript
  • 00:15:35 folder in the source folder but here's
  • 00:15:38 an important thing a service worker
  • 00:15:40 always has a scope scope defines which
  • 00:15:43 pages a service worker can control
  • 00:15:45 because a service worker is JavaScript
  • 00:15:48 but not like your normal JavaScript like
  • 00:15:51 here in the app dot J's file a service
  • 00:15:54 worker isn't attached to a single page a
  • 00:15:56 single file this app dot J's file is it
  • 00:15:59 gets loaded by the index.html file here
  • 00:16:01 at the bottom and it is attached to this
  • 00:16:04 fall this is the reason why in app dot
  • 00:16:06 ajs we can access the Dom off this
  • 00:16:09 index.html file now a service worker is
  • 00:16:12 also rich
  • 00:16:14 through your pages but I'm deliberately
  • 00:16:16 saying page s because you could add it
  • 00:16:18 on any page but then it runs in the
  • 00:16:22 background on a separate fret so not on
  • 00:16:25 your main UI thread like this script
  • 00:16:27 file runs but on a separate fret this
  • 00:16:30 also means that for example on Android
  • 00:16:33 it will keep on running even if your
  • 00:16:35 page is closed which is amazing for
  • 00:16:37 getting push messages for example
  • 00:16:39 something I do show in my udemy course
  • 00:16:41 so this is a serviceworker it runs on a
  • 00:16:44 separate fret it's not connected to a
  • 00:16:47 single page but instead it has a scope
  • 00:16:50 which could be your entire domain all
  • 00:16:52 the pages on the domain or a subset if
  • 00:16:55 you limit the scope to a given folder in
  • 00:16:57 your domain on your web page here so to
  • 00:17:00 say and that's the important thing if I
  • 00:17:02 were to add my serviceworker in this
  • 00:17:04 javascript file the serviceworker could
  • 00:17:07 only interact with pages stored in the
  • 00:17:11 javascript file or in sub pages that of
  • 00:17:14 course isn't helpful because we haven't
  • 00:17:16 any pages in there so we should create
  • 00:17:18 the serviceworker on the public folder
  • 00:17:20 here so I'll create a new file and you
  • 00:17:22 can name this file whatever you want
  • 00:17:24 I'll name it s wjs this is a file which
  • 00:17:29 will hold my serviceworker related
  • 00:17:31 javascript code and again it's not
  • 00:17:33 attached to a single page it is
  • 00:17:35 event-driven and it can list is to
  • 00:17:37 events fired by any of your pages or
  • 00:17:40 other events not even coming from your
  • 00:17:42 pages like incoming push notifications
  • 00:17:44 now here I want Q react to some events
  • 00:17:50 triggered by my index.html fault though
  • 00:17:52 and first of all we should register this
  • 00:17:56 serviceworker this is done in JavaScript
  • 00:17:59 and of course in your normal JavaScript
  • 00:18:01 because you have to tell the browser hey
  • 00:18:04 here's a serviceworker related to my
  • 00:18:06 page or a subset of my pages please
  • 00:18:09 register it and if the browser doesn't
  • 00:18:12 notice serviceworker yet or the
  • 00:18:14 serviceworker file changed so if the
  • 00:18:16 file size changed the browser will take
  • 00:18:19 the serviceworker
  • 00:18:20 and register it override the old one or
  • 00:18:23 register it as a new one to code to
  • 00:18:26 register a service program
  • 00:18:27 therefore as I said has to be added in
  • 00:18:29 the app dot JS file or directly in a
  • 00:18:32 script part in the index.html file and
  • 00:18:34 in there
  • 00:18:36 I'll now simply add navigator that
  • 00:18:39 refers to the browser Service Worker dot
  • 00:18:43 register now here's an important thing
  • 00:18:46 you should make sure that this code
  • 00:18:48 where you register a serviceworker gets
  • 00:18:50 executed on every page in your
  • 00:18:52 application so that the user if he
  • 00:18:56 Wizards a different page and not your
  • 00:18:57 main page if you had multiple ones so
  • 00:19:00 that even if the user wizard at some
  • 00:19:02 other page like slash about that he
  • 00:19:04 still installs the serviceworker and
  • 00:19:06 then again you have one serviceworker
  • 00:19:08 for all the pages so it's always the
  • 00:19:10 same one you register but the user might
  • 00:19:12 enter a different place a different path
  • 00:19:14 in your app so you should be prepared
  • 00:19:15 for this back to the registration code
  • 00:19:19 there you pass an argument to register
  • 00:19:22 and that simply skip off to the
  • 00:19:23 serviceworker file so in this case it's
  • 00:19:26 /s wjs pointing to the root folder and
  • 00:19:30 then s wjs this is the serviceworker i
  • 00:19:32 want to register now we have one issue
  • 00:19:35 here though this code will work phone
  • 00:19:37 will work fine on Chrome on the latest
  • 00:19:39 version however what if the user uses a
  • 00:19:42 browser which doesn't support service
  • 00:19:44 workers we can check serviceworker
  • 00:19:47 support on his serviceworker ready this
  • 00:19:50 is a page on check our cobalt github do
  • 00:19:52 link can be found in the video
  • 00:19:54 description and on this page you see the
  • 00:19:56 different serviceworker features and
  • 00:19:58 which browsers supported or are working
  • 00:20:01 on it and you see that Chrome and
  • 00:20:03 Firefox support is decent but that
  • 00:20:05 Safari and AD are working on
  • 00:20:07 serviceworker features the general
  • 00:20:10 features or some special features so if
  • 00:20:13 the user uses Safari or edge right now
  • 00:20:16 the code we wrote here this one will
  • 00:20:19 throw an error because the browser can't
  • 00:20:22 handle this
  • 00:20:23 there is no serviceworker object on the
  • 00:20:25 browser so what we should do is we
  • 00:20:27 should wrap this into AF check where we
  • 00:20:29 say if service worker in navigator so if
  • 00:20:35 this object exists in the navigator then
  • 00:20:37 we want to execute this code otherwise
  • 00:20:39 we won't register a service worker
  • 00:20:42 that of course means we don't have
  • 00:20:43 access to the features we are about to
  • 00:20:45 add but that doesn't matter because the
  • 00:20:47 browser doesn't support it anyways so
  • 00:20:50 with that we were just sir to Service
  • 00:20:51 Worker now we can fill the service
  • 00:20:54 worker with some life let's go to the
  • 00:20:56 service worker and I said that the
  • 00:20:58 service worker is event driven you
  • 00:21:00 always react to events in there so what
  • 00:21:03 you can do is you can add an event
  • 00:21:05 listener you add it on self this refers
  • 00:21:08 to the service worker process so to say
  • 00:21:11 and then you call add event listener and
  • 00:21:13 now there is no click event or something
  • 00:21:16 like that because we're not reacting to
  • 00:21:18 Dom events here because the service
  • 00:21:20 worker is decoupled from the Dom you
  • 00:21:22 can't access the Dom in a service worker
  • 00:21:24 but there are other events or events
  • 00:21:26 available for example the install event
  • 00:21:29 this will be fired when a service worker
  • 00:21:31 is you guessed it installed which is the
  • 00:21:34 case as I mentioned if it's brand-new or
  • 00:21:36 if it's an updated version and the
  • 00:21:38 browser replaces the existing one for
  • 00:21:41 the given scope for the given domain in
  • 00:21:42 this case so if the install event fires
  • 00:21:45 then I want to execute a function here
  • 00:21:48 and in this function of first of all
  • 00:21:51 simply log service worker installed this
  • 00:21:55 is something I can do here
  • 00:21:56 now we'll soon add more code to the
  • 00:21:58 install event though let's also listen
  • 00:22:01 to the activate event here now in the
  • 00:22:04 activate event we know that it has been
  • 00:22:07 activated and the difference between
  • 00:22:09 installing and activating is that
  • 00:22:12 installation happens instantly if the
  • 00:22:14 browser detects a new service worker but
  • 00:22:16 it will keep it waiting until it
  • 00:22:18 activates until you or the user using
  • 00:22:21 your page closed all tabs in his browser
  • 00:22:24 where your page was open the reason for
  • 00:22:26 it is is simple if you install a new
  • 00:22:28 service worker and you overwrite the old
  • 00:22:30 one if you would immediately activate
  • 00:22:33 and replace the old one then you might
  • 00:22:35 break the air page the user is currently
  • 00:22:37 visiting because maybe your page is
  • 00:22:39 firing somebody went to which the
  • 00:22:41 service worker should react and you
  • 00:22:42 suddenly push a new version onto this
  • 00:22:45 page now existing processes might get
  • 00:22:48 interrupted the page might not work
  • 00:22:50 anymore that is why we have two separate
  • 00:22:52 steps here
  • 00:22:53 it will only activate after user closed
  • 00:22:56 all tabs and then open it again then the
  • 00:22:59 installed service worker will get
  • 00:23:01 activated so these are two events we can
  • 00:23:03 see here now let me also go back to the
  • 00:23:06 app dot JS file and chain something to
  • 00:23:09 the registration the register method
  • 00:23:11 returns a promise and therefore here I
  • 00:23:14 can execute a function where I can
  • 00:23:16 simply log service worker registered now
  • 00:23:21 with all that added let's see this in
  • 00:23:24 action so the server is still running
  • 00:23:26 I'll go back to my application here and
  • 00:23:29 I'll reload it now if you go to service
  • 00:23:32 workers here you should see that a
  • 00:23:34 service worker was registered and this
  • 00:23:37 is the scope of your service worker this
  • 00:23:39 domain here's the service worker file
  • 00:23:41 you see it's activated and it is running
  • 00:23:43 and this is your first service worker
  • 00:23:46 added now the service worker like this
  • 00:23:50 doesn't do too much though you typically
  • 00:23:53 the most basic use that you can do you
  • 00:23:55 typically use it for caching caching
  • 00:23:58 means that you can actively add some
  • 00:24:00 files to your cache a special cache not
  • 00:24:03 the default browser cache and you can
  • 00:24:06 also define when these assets should be
  • 00:24:08 served so that you make sure that your
  • 00:24:10 page even works if you're offline let's
  • 00:24:14 add such a functionality in the service
  • 00:24:15 worker and the best place to catch some
  • 00:24:18 files which you know will not change
  • 00:24:20 that often you always want to be able to
  • 00:24:22 access them is in the installed step
  • 00:24:24 here because there you can pre cache the
  • 00:24:27 static assets off your page you do this
  • 00:24:30 by simply reaching out to the cache API
  • 00:24:34 a special web API which allows you to
  • 00:24:37 access this special cache I was talking
  • 00:24:39 about not the default browser cache but
  • 00:24:41 a cache you can manage you can use
  • 00:24:44 caches open to open a cache there next
  • 00:24:48 you pass a name and this could be static
  • 00:24:51 or whatever you like if it doesn't exist
  • 00:24:53 yet like it does for the first time you
  • 00:24:55 execute this it will simply create it
  • 00:24:57 and thereafter it will open this cache
  • 00:24:59 caches open returns a promise and in the
  • 00:25:03 function which gets executed once the
  • 00:25:05 promise resolves we get access to the
  • 00:25:07 opened cache so let's pass this as an
  • 00:25:09 argument now in this open cache we can
  • 00:25:12 call the add method to now add an asset
  • 00:25:16 for caching now the add method is pretty
  • 00:25:18 cool we can simply add a path to an
  • 00:25:21 asset here and the browser will
  • 00:25:23 automatically make an HTTP request to
  • 00:25:26 the browser and store the incoming
  • 00:25:28 response in the cache it will actually
  • 00:25:30 store a key value pair in the cache
  • 00:25:32 where the key is your request and the
  • 00:25:35 response is well excuse me and the value
  • 00:25:37 is the response you got back so here we
  • 00:25:40 can simply specify a path like for
  • 00:25:42 example let's say we want to cache the
  • 00:25:44 app.js file so we could cache source J s
  • 00:25:49 AB dot J s we also might want to just
  • 00:25:53 cache slash so that if we wizard just
  • 00:25:56 localhost:8080 1 nothing else we have
  • 00:25:59 this response cached we should also
  • 00:26:01 cache slash index.html because that's
  • 00:26:03 not the same as just slash both load the
  • 00:26:06 same file and yet but is these are
  • 00:26:08 different requests to different
  • 00:26:10 endpoints now with that we would already
  • 00:26:13 cache quite some files we wouldn't cache
  • 00:26:16 any images and CSS and so on though and
  • 00:26:18 you can see that you're calling cache
  • 00:26:20 add a lot now that's fine but I'll
  • 00:26:22 comment it out there is another function
  • 00:26:25 which is cache at all cash add all takes
  • 00:26:28 an array of strings and simply does all
  • 00:26:30 these individual additions automatically
  • 00:26:33 in one turn so here again you can now
  • 00:26:36 cache slash slash index.html so this is
  • 00:26:40 just an area of strings as I said source
  • 00:26:42 JSF J's and what else we have
  • 00:26:45 like for example source CSS and in there
  • 00:26:49 we have the app CSS file now we also
  • 00:26:53 might want to store an image so here we
  • 00:26:55 could now store source image as PW a dot
  • 00:27:00 JPEG you could also store the icons here
  • 00:27:03 now I will store something else though
  • 00:27:06 if we have a look at the index.html file
  • 00:27:08 there you will see that we're also
  • 00:27:11 reaching out to a CDN to fetch this font
  • 00:27:14 so what I'll do is I'll also try to
  • 00:27:17 catch this so I'll copy this URL you can
  • 00:27:20 cash assets from Abra service – it's not
  • 00:27:23 just from your server you can enter any
  • 00:27:25 URL into the cache add method so I'll
  • 00:27:29 reach out to this CDN here by simply
  • 00:27:32 adding this URL here queue and keep in
  • 00:27:35 mind these are all just you are else
  • 00:27:37 these are relative URLs on your own
  • 00:27:40 server and this is a URL reaching out to
  • 00:27:43 an average server in the end the browser
  • 00:27:45 will make these requests and store the
  • 00:27:48 response for you
  • 00:27:49 this code won't work though service
  • 00:27:53 workers are only idle working for an
  • 00:27:57 unknown period of time and then they
  • 00:27:59 will shut down to make sure that the
  • 00:28:01 service worker doesn't shut down before
  • 00:28:03 cashing is done we can take advantage of
  • 00:28:06 the event which we get passed into this
  • 00:28:07 function for the installation event
  • 00:28:10 automatically this event has a wait
  • 00:28:14 until method and we should execute this
  • 00:28:17 to make sure that this recruit waits for
  • 00:28:19 a certain process to finish before it
  • 00:28:21 possibly shuts down and shutting down
  • 00:28:23 doesn't mean instead it's just passed so
  • 00:28:26 to say and it will wake up the next time
  • 00:28:28 it receives an event now we can take
  • 00:28:31 cache open which returns a promise and
  • 00:28:33 pass it to wait until wait until
  • 00:28:36 conveniently expects to get a promise so
  • 00:28:38 this is just fine now with that it will
  • 00:28:41 wait for this process here to finish
  • 00:28:44 before it possibly goes into idle mode
  • 00:28:46 again now let's try this out let's save
  • 00:28:49 this keep in mind we now change the
  • 00:28:51 serviceworker file so the fault size
  • 00:28:53 changed so the browser should install
  • 00:28:55 the new one the next time we refresh the
  • 00:28:58 page so let's do that let's refresh the
  • 00:29:00 page and there you now see if you go to
  • 00:29:03 applications service workers then we get
  • 00:29:06 a new service worker waiting to activate
  • 00:29:08 in the console we therefore see that it
  • 00:29:11 was registered that it was installed but
  • 00:29:14 that it wasn't activated yet to activate
  • 00:29:17 it we have to close this page and reopen
  • 00:29:21 it close all active tabs with the page
  • 00:29:24 and the next time you visit your
  • 00:29:25 developer tools
  • 00:29:26 you see it's activated and running
  • 00:29:28 you'll also see also under application
  • 00:29:31 if you go to cache storage
  • 00:29:33 and right-click it to refresh you'll see
  • 00:29:36 there is a static cashier this static
  • 00:29:39 cash actually cashed all the requests
  • 00:29:42 you specified in your service worker you
  • 00:29:45 also see the response here and the date
  • 00:29:47 and time when twas cashed now with that
  • 00:29:50 we haven't gotten offline support yet
  • 00:29:52 though all these things are cached but
  • 00:29:55 we never try to fetch them so what we
  • 00:29:57 can do is we can add a new event
  • 00:29:59 listener to this service worker and this
  • 00:30:02 is for the fetch event now the fetch
  • 00:30:04 event is for example triggered whenever
  • 00:30:06 you fetch something in the index.html
  • 00:30:08 file like through this link or fruit
  • 00:30:10 desolating to the apt osseous follow or
  • 00:30:13 through this line link pointing to the
  • 00:30:14 script file whenever this is the case a
  • 00:30:17 fetch event is registered in the service
  • 00:30:20 worker now for the fetch event we can
  • 00:30:23 now react with a function where we also
  • 00:30:26 get an event as an argument and now
  • 00:30:28 there we can decide what we want to do
  • 00:30:30 if we don't do anything the default will
  • 00:30:33 happen the browser will go ahead reach
  • 00:30:35 out to the network and make that request
  • 00:30:37 but we can change that behavior we can
  • 00:30:40 basically use our service worker like a
  • 00:30:42 network proxy here we can use event and
  • 00:30:47 now not wait until but respond with to
  • 00:30:50 make sure we respond with something
  • 00:30:52 different than the default Network
  • 00:30:54 request now here we could respond with
  • 00:30:57 our own fetch request to some other URL
  • 00:31:00 or we simply reach out to their cache
  • 00:31:02 and try to find the given network data
  • 00:31:06 from that cache get it from the cache
  • 00:31:08 the data we wanted to get I mean we can
  • 00:31:12 do this with the caches API again and
  • 00:31:14 there we have a match method this allows
  • 00:31:17 us to match the incoming requests with
  • 00:31:20 some resource in our in our cache so we
  • 00:31:25 should simply pass event requests there
  • 00:31:27 is a request up a request object on an
  • 00:31:30 event object and now the cache API will
  • 00:31:33 have a look if in any of its caches in
  • 00:31:35 this case we only have one but it could
  • 00:31:37 have multiple ones if in any of the
  • 00:31:39 caches it finds this request and for
  • 00:31:42 some assets it should indeed do that if
  • 00:31:46 that's the case or actually always it
  • 00:31:49 will then execute a function where we
  • 00:31:52 get their response from the cash from
  • 00:31:55 the cash not from the network back now
  • 00:31:58 this will also be executed if it doesn't
  • 00:32:01 find something in the cache so it will
  • 00:32:03 not fail it will not throw an error
  • 00:32:04 response will then just be null if
  • 00:32:07 response is set though we can simply
  • 00:32:11 return the response so we return the
  • 00:32:13 response from the cache if we have it in
  • 00:32:15 there else
  • 00:32:17 we can simply do something well else we
  • 00:32:20 can reach out to the network so we can
  • 00:32:21 then make the fetch with the fetch API
  • 00:32:24 this is supported by all more modern
  • 00:32:27 browsers and since we're in a
  • 00:32:28 serviceworker which only runs on modern
  • 00:32:30 browsers we can safely access this so
  • 00:32:33 fetch is now available and fetch will
  • 00:32:35 now make a network request to event
  • 00:32:39 request for example and there we can
  • 00:32:41 then simply return fetch which is of
  • 00:32:43 course a promise but we can return a
  • 00:32:47 promise or directly response both will
  • 00:32:50 work here in caches match and this code
  • 00:32:52 should make sure that if we have the
  • 00:32:54 request in the cache we get the response
  • 00:32:57 from the cache if we don't find it in
  • 00:32:59 there we go ahead and make that Network
  • 00:33:01 request let's see if that works
  • 00:33:04 let's save this and let's reload the app
  • 00:33:06 to install the new serviceworker now as
  • 00:33:09 before it's waiting to activate so let's
  • 00:33:11 simply close that tap and reopen it and
  • 00:33:14 let's have a look it was activated now
  • 00:33:17 let's see if this works if I reload this
  • 00:33:19 all works but now under a serviceworker
  • 00:33:21 here an application
  • 00:33:23 let's go offline and let's reload the
  • 00:33:25 app again and even though I'm offline
  • 00:33:28 I am offline this is simulating that I'm
  • 00:33:31 offline the app looks like before and
  • 00:33:33 it's the works like before I can still
  • 00:33:35 tap this the reason for it is this and
  • 00:33:38 we can confirm this if we have a look at
  • 00:33:39 the network tab that we're getting these
  • 00:33:42 assets from the serviceworker here you
  • 00:33:44 see that from the serviceworker we're
  • 00:33:46 fetching it from there that's of course
  • 00:33:48 the cool thing because now we got an
  • 00:33:50 offline ready application with a
  • 00:33:53 serviceworker
  • 00:33:54 now you can find whom this whole caching
  • 00:33:57 and get something from the cache thing
  • 00:34:00 way more there are different strategies
  • 00:34:02 you can use to get something from the
  • 00:34:04 cache first but then reach out to the
  • 00:34:06 network to get a more up-to-date version
  • 00:34:08 of that asset but to go to the cache
  • 00:34:10 first to show something on the screen
  • 00:34:12 immediately and so on and I will walk
  • 00:34:14 through all these strategies in my udemy
  • 00:34:17 course which I mentioned at the
  • 00:34:18 beginning linked in the video
  • 00:34:19 description this basic caching here the
  • 00:34:22 spree caching we're doing here
  • 00:34:24 already is a huge first step though now
  • 00:34:27 with that let's see how that looks like
  • 00:34:29 on a real device it should actually all
  • 00:34:32 work on an Android emulator for example
  • 00:34:35 a one you create through the Android
  • 00:34:37 studio so feel free to do that if you
  • 00:34:39 don't have a real Android device I'll
  • 00:34:42 quickly connect my real device with my
  • 00:34:44 computer though and then I'll try to see
  • 00:34:46 this run on the device and see how the
  • 00:34:49 application looks there now I connected
  • 00:34:52 my real Android phone with my Mac here
  • 00:34:54 and the cool thing is on Chrome which
  • 00:34:57 you have Chrome on your Android device
  • 00:34:59 again should also work on an emulator
  • 00:35:01 and you have Chrome on your Mac and
  • 00:35:04 somewhere on your Windows machine – as
  • 00:35:06 your default browser you can go to the
  • 00:35:09 developer tools on Chrome for desktop
  • 00:35:11 these free dots you see in the top right
  • 00:35:13 corner and then more tools and then
  • 00:35:16 remote devices now if you expand this
  • 00:35:19 here this a simple window you actually
  • 00:35:22 see all connected Android devices now
  • 00:35:25 there you should also make sure that you
  • 00:35:27 check port forwarding so that you can
  • 00:35:29 visit a port which a server I should say
  • 00:35:33 running on your local machine on your
  • 00:35:35 desktop machine here also from your
  • 00:35:37 mobile device because by default if you
  • 00:35:39 enter localhost 8080 one on your real
  • 00:35:42 mobile device or the emulator this will
  • 00:35:45 not be your page on your machine here
  • 00:35:48 this will be localhost on the device
  • 00:35:51 which is the device itself but with port
  • 00:35:53 forwarding you can make sure that you
  • 00:35:55 could enter localhost 8080 1 on your
  • 00:35:57 device and wizard the server running on
  • 00:35:59 your Mac or Windows machine so with that
  • 00:36:03 let's now simply go to that connect
  • 00:36:06 device my oneplus here and there I now
  • 00:36:10 will simply open a new tab so let me
  • 00:36:13 quickly do that
  • 00:36:14 so now here in Chrome for my desktop
  • 00:36:17 machine I can inspect this tap I opened
  • 00:36:21 and I now got the same developer tools I
  • 00:36:23 have on my Mac Chrome here on my Mac
  • 00:36:28 still this window is running on the Mac
  • 00:36:29 but it's referring to the page running
  • 00:36:32 on my mobile device which I can show by
  • 00:36:35 tapping here and so on
  • 00:36:36 and you see I already get this
  • 00:36:38 installation banner here you can also
  • 00:36:41 manually trigger it by going to manifest
  • 00:36:44 and then clicking add to homescreen any
  • 00:36:46 developer tools connected to your device
  • 00:36:48 now I'll click Add here and now it's
  • 00:36:51 again well as I just said adding it to
  • 00:36:53 my home screen we now have a look at
  • 00:36:56 that here it is quite a bit here it
  • 00:37:00 opens and this is now opened through the
  • 00:37:03 icon on the home screen now right now at
  • 00:37:06 the point of time I'm recording this
  • 00:37:07 this is a bit buggy at least for a
  • 00:37:10 localhost
  • 00:37:10 testing there you see it still looks
  • 00:37:13 like it's running on the browser even
  • 00:37:15 though I opened it from this icon and I
  • 00:37:18 promised you that it would look like as
  • 00:37:20 like a standalone app at least since we
  • 00:37:22 displayed a set display to stand alone
  • 00:37:25 in the manifest now on localhost we get
  • 00:37:28 this back we don't get it if we surf
  • 00:37:30 this from HTTP though so why don't we
  • 00:37:33 quickly do that as an extra bonus task
  • 00:37:36 to make sure to really shift us to a
  • 00:37:38 real page so we can see how it would
  • 00:37:41 work if we were to serve it from HTTPS
  • 00:37:45 now you can upload it to any of your
  • 00:37:47 favorite hosting providers as long as
  • 00:37:50 you ensure that your application or your
  • 00:37:52 hosting your server – ship the app
  • 00:37:55 through HTTP I will use firebase because
  • 00:37:57 it's super simple to setup and super
  • 00:37:59 simple to get started so I'll quickly
  • 00:38:01 head over to firebase and there I'll go
  • 00:38:04 to the console to create a new project
  • 00:38:06 for that and again you can use any other
  • 00:38:08 hosting provider as long as your app is
  • 00:38:10 served over HTTP so here I will name
  • 00:38:14 this basic PWA
  • 00:38:17 and region can be whichever region you
  • 00:38:20 want Germany and create this project now
  • 00:38:23 firebase also offers a lot of other
  • 00:38:26 features like database which
  • 00:38:28 she was at all here I'm just interested
  • 00:38:29 in their hosting so once it is finished
  • 00:38:33 I want you well host my app here so if I
  • 00:38:37 click on hosting and click on get
  • 00:38:39 started you get instructions on how to
  • 00:38:41 host your application and first of all
  • 00:38:44 you should install the firebase tools
  • 00:38:46 again of course only relevant if you are
  • 00:38:48 using firebase so I'll quit my local
  • 00:38:51 development server and I'll quickly
  • 00:38:53 install the firebase tools globally on
  • 00:38:55 my machine with sudo and people install
  • 00:38:58 – gee firebase tools does basically a
  • 00:39:01 seal i buy firebase which allows us to
  • 00:39:03 do some things like easily deploying it
  • 00:39:06 to our web server now once this is
  • 00:39:08 finished we can simply click continue
  • 00:39:10 here in this window to see the next
  • 00:39:12 tasks we should sign in and then initiai
  • 00:39:16 initiate our project now I already am
  • 00:39:19 signed in so I'll type firebase init
  • 00:39:21 here to put this project folder under
  • 00:39:23 control of firebase and I'll simply just
  • 00:39:26 check posting here by hitting the tab
  • 00:39:28 bar in this drop-down in this menu and
  • 00:39:30 then hit enter and this will now set us
  • 00:39:33 up to be a host of a project now I have
  • 00:39:36 to pick the project and its basic PWA
  • 00:39:38 for me the project just to create it
  • 00:39:41 I'll confirm that my route web directory
  • 00:39:44 should be the public directory which is
  • 00:39:46 the default
  • 00:39:47 I will check no here it's not a single
  • 00:39:50 page application though that
  • 00:39:51 theoretically would theoretically would
  • 00:39:52 be one and you could write Y for yes
  • 00:39:55 here but I'll write no and I don't want
  • 00:39:58 to override the public index.html file
  • 00:40:00 so I'll enter n here for no to with that
  • 00:40:03 it's initialized and the last step is Q
  • 00:40:06 enter firebase deploy so let's run this
  • 00:40:09 deployed to ship this project to a
  • 00:40:13 server and once this is done we'll also
  • 00:40:16 get the URL under which we can wizard
  • 00:40:18 this here Q so let's wait for this to
  • 00:40:21 finish real quick and now that it
  • 00:40:23 finished des is the URL where we can
  • 00:40:25 wizard our project let's quickly check
  • 00:40:27 it here on Mac so I'll quickly enter it
  • 00:40:29 here instead of localhost looks good
  • 00:40:32 looks very good let's reload this one
  • 00:40:34 more time let's now try offline mode
  • 00:40:37 here by going offline it's looking days
  • 00:40:39 decent now let's try it on the mobile
  • 00:40:41 the
  • 00:40:42 so there I'll visit the same URL of
  • 00:40:44 course you should enter your URL and I
  • 00:40:46 see my project here I'm also asked
  • 00:40:48 whether I want to add it to your home
  • 00:40:49 screen or not so I'll quickly do that
  • 00:40:51 and once it has the same icon it's a
  • 00:40:53 different app for my phone here because
  • 00:40:56 it's not running on localhost and now if
  • 00:40:58 I tap this icon now you see what I meant
  • 00:41:01 it's running standalone like a real app
  • 00:41:03 and if I open the task switcher here you
  • 00:41:07 actually see this here is the app with
  • 00:41:09 the theme color you can see the blue
  • 00:41:11 toolbar and here is Chrome so it's
  • 00:41:14 running as a separate process even
  • 00:41:16 though technically it still runs powered
  • 00:41:18 by Chrome it still uses Chrome it still
  • 00:41:20 is a web app but it looks like a native
  • 00:41:22 app it behaves like one so that's the
  • 00:41:24 cool thing here we got this application
  • 00:41:26 and finally if I check offline mode here
  • 00:41:28 – by simply going into airplane mode
  • 00:41:31 real quick if I now reload the app you
  • 00:41:34 see it's still working it's still
  • 00:41:36 working fine here and now if I reenable
  • 00:41:39 Internet we're back to the online
  • 00:41:41 experience so that's the cool thing this
  • 00:41:44 is how it looks like if we run it on a
  • 00:41:46 real server again any server you like as
  • 00:41:48 long as it's over HTTPS since that is a
  • 00:41:51 serviceworker requirement and i hope
  • 00:41:53 this video gave you some insights into
  • 00:41:55 how to create a basic progressive web
  • 00:41:57 app which is installable and which pre
  • 00:42:00 caches some files to give you a basic
  • 00:42:03 offline functionality if you want to
  • 00:42:05 dive much deeper check out my you deme
  • 00:42:07 course and of course i'd be more than
  • 00:42:09 happy to also welcome you in all the our
  • 00:42:11 future videos on this channel bye