How to Build Websites that work without Internet Using Angular, Service Workers and Firebase
In this article, you will learn the theory of how service workers work. I provide a short tutorial to apply that theory to make a website that runs without the internet. Finally, I’ll discuss what this means for you and the future of the internet.
App that works without the internet (offline-first) • The Website: demo.atila.ca • Theory on how service workers work • Application: Live Practical Tutorial on how to build offline-first web apps • Bonus: Rant on Why this is awesome 2
at Ivey Business school, Canada • Founder atila.ca, easily find and apply to scholarships. • Founder of software engineering studio, tech.atila.ca • Software Engineering Intern @ Properly, Employee #2 • My Website: tomiwa.ca • Follow me on Twitter: @tomiwa1a 5
one flaw • Alibaba $25 billion in sales in one day (singles day) • 40% of cloud computing clients Amazon Web Services Including: Apple, Netflix and CIA • 2.2 Billion people use Facebook every month, 700 million Instagram • But without wifi, the entire site is unusable 7
for you • Humble, little atila.ca has much fewer users • But with or without internet you can still use atila.ca • Google Drive also does this really well 9
browser and the internet • When your web app asks for resources (images, html files, json API etc.) the service worker gets it for you without asking internet • In literal terms, it is a javascript file that gets shipped along with the rest of your app 13
and tries to fulfill the request itself • First it checks its local cache to see if it has the resources you need • If it doesn’t: a. Goes to the network and asks for the resources b. Saves resources to its local cache c. Serves you the resources from its cache • Works both with and without internet a. Faster connections even with internet How Does It Work? 14
node 8.X or greater (node -v ) and npm 5.x or greater ( npm -v) • Globally install Angular CLI ◦ npm install -g @angular/cli • Google Chrome Browser (optional, but recommended) • Google Account (optional if you want to deploy to Firebase) 16
Clone the demo.atila.ca web app from Github: atila-web-app ◦ Checkout the pwa-tutorial branch: git checkout pwa-tutorial ◦ Checkout the tutorial start commit: git checkout pwa-tutorial-0.0 ◦ Install npm modules: npm install ◦ Start the app!” ng serve -o ◦ If you get an No NgModule error. Go to any .ts file and put a space ▪ Very weird bug! Learn More 17
a. npm install @angular/[email protected] --save 2. Tell angular-cli to build project with service worker: a. ng set apps.0.serviceWorker=true 3. Configure your service worker in ngsw-config.json 4. Add a manifest.json file and reference it in index.html Further Reading: • Transforming an existing Angular application into a Progressive Web App • Turning an Angular 6 app into a Progressive Web App 18
--save: ◦ This module contains the service worker objects that we will be using in the next step • Ng set apps[0].serviceWorker=true: ◦ Tell angular CLI to automatically produce a javascript file that contains the code for the service worker, when building project explained in next step 20
what files it should be saving and how it should be saving them: • assetGroups: files that are included as part of the app, ◦ When the app updates, these resources update as well • dataGroups: external resources not versioned with app • Install Mode: What caching strategy to use when first seeing this file • UpdateMode: What caching strategy to use when updating the file, after we’ve already installed it • Caching strategy: ◦ Prefetch: Save these files before we even ask for it ◦ Lazy: Save these files only after they’ve been requested at least once 21 Further Reading: • https://angular.io/guide/service-worker-config Github Gist / Github Diff
web app to a progressive web app ◦ Basically a web app that behaves like a native mobile app • Allows users to install your app to home screen • Add the home screen icon • Reference it in index.html 22 { "name": "Atila", "short_name": "Atila", "start_url": "index.html", "display": "standalone", "icons": [{ "src": "assets/img/favicon-bg.png", "sizes": "512x512", "type": "image/png" }], "background_color": "#194f87", "theme_color": "#194f87" } Further Reading: • Google Web Fundamentals: Add to Home Screen • Google Web Fundamentals: Web App Manifest
worker exists • Add the service worker module to app.module.ts • Register the service worker in main.ts ◦ Check if the browser has service worker support // src/main.ts if ('serviceWorker' in navigator && environment.production) { console.log("Service Worker in main.ts"); window.addEventListener('load', () => { console.log("on page Load Service Worker in main.ts"); navigator.serviceWorker.register('/ngsw-worker.js', { scope: '/', }) .then(registration => { console.log("Service Worker registration completed main.ts", registration); }); }); 23 // src/app.module.ts import {ServiceWorkerModule} from '@angular/service-worker'; … Imports: [ …, ServiceWorkerModule.register('/ngsw-worker.js', {enabled: environment.production}),]
based on the instructions from the ngsw-config.json files • It tells your serviceworker to cache any of the files in this list • Caching strategy: ◦ Prefetch: Save these files before we even ask for it ◦ Lazy: Save these files only after they’ve been requested at least once 26
the service worker • We registered it earlier in our main.ts file • A plain javascript file containing the code and logic for how your service worker registers and caches your service worker to database • If you’re up for a challenge, try looking through the code and see if you can understand what is happening • Add Screenshot of ngsw.js 27
an offline contexts, so we need a server that can simulate offline environments • Install npm http server ◦ Npm install [email protected] --save-dev • Build and Run the server ◦ ng build --prod (optional) ◦ http-server -p 8080 -c-1 dist 29
devtools ◦ Do this before going to localhost! ◦ Open a new tab ◦ Right click somewhere blank on screen ◦ Inspect > go to Network Tab • Open http://localhost:8080/ 30 • Note that there is no wi-fi in top right • See console: The external network resources fail with 504 but our files are succesful (200)
tab in Devtools and you will see local cache section • This is the “database” where the service workers are saving your files • That’s it! You now have a simple but fully functional offline first web app. Continue to part 2 for adding more cool features 31 Further Reading: • Angular University: Angular Service Workers
try to click on a link, you will notice a server error • Your service worker doesn’t have those APIs in your database, but we can add it • Pop Quiz! If we want to tell our service worker to cache a new type of file where should we put the code to do so: a. Manifest.json b. Ngsw-config.json c. app.module.ts 33
our ngsw-config.json to cache external API urls as well • Two caching options a. Freshness: Go to the network first, if missing, go to the b. Performance: Go the cache first, then go to network 34 Github Diff Further Reading: • https://angular.io/guide/service-worker-config
use a seperate URL that allows your app to access it via CORS • We will use a special JSON service to simulate (“mock”) our blog API ◦ Since We don’t have permission to use official Atila API’s • Change ScholarshipService.getPaginatedScholarships: ◦ Go to src/app/_service/scholarship.service.ts#L47 ◦ Change: this.http.post(`${this.scholarshipsPreviewUrl}?page=${page}/`, form_data) ◦ To: this.http.get(`https://api.myjson.com/bins/dx1dc`) • Change BlogPostService.getBySlug: ◦ Go to src/app/_service/blog-post.service.ts#L25 ◦ Change: this.http.get(`${this.blogUrl}blog/${username}/${slug}/`) ◦ To: this.http.get(`https://api.myjson.com/bins/v5ow0`) 35
available from network, service worker still serves the old version in cache to save time • Add your profile to team page ◦ src/app/team/team.component.ts ◦ Add your image and some information in the team data array • Rebuild project and restart server • You’ll notice that your profile doesn’t appear yet 37
restart server • We can add a snackbar to notify user of new updates ◦ npm install @angular/[email protected] --save (you might already have this) • Then we create swUpdate to listen for updates from the SW and update if a new version is available.Github Diff • Rebuild and reserve your application (see slide 24) 38
service worker we should probably deploy it to a real website: Deployment Prerequisites: 1. Create a google account 2. A firebase account and a firebase project 3. install firebase tools globally: npm install -g [email protected] 4. Log in to firebase: firebase login 40 Further Reading: Angular Firebase - Deploying an Angular App to Firebase
2. Choose the following settings: ◦ Choose hosting as the project type ◦ Change public folder to dist/ ◦ Configure as a single page app ◦ Overwrite idnex.html? NO 3. Deploy! Firebase deploy 4. Visit the url in the command line output to see your app 41
your favorite NY Times articles or • Read your twitter “while you were gone” tweets • While on the plane! • Imagine if you could save your Amazon shopping cart and read the product reviews while on train to work in morning • The next 1 billion users of internet have poor internet connection: think of how this benefits them • With service workers all this and more is possible 43
notifications (story for another day), why make a native mobile app? • See this article for why startups and companies should consider web apps: ◦ Tl:dr native apps are hard because of: app store gatekeepers, supporting 2 different platforms (ios, Android), no one wants to download another app, 44
really consider if building a native mobile app is worth it or is a PWA a better choice • When building your web app don’t let lack of internet be a constraint, it should be a feature! ◦ Hard to compete for users attention when there is internet ◦ Imagine if you are one of the few apps that works when there is no internet 45