From Web to App 4

FWTA is a project embraces the vision to create cross-platform mobile first applications using morden web technologies and best practices, such as Server Side Rendering (SSR), Progressive Web Application (PWA), Accelerated Mobile Pages (AMP), PRPL Pattern, Severless Backend.

This is one of the article series which records thoughts and notes during my implementation of FWTA.

In the previous article, I have added some UI to the web app to make it more like a native app. I will add PWA support to achieve the goals below:

  • Add web app to home screen and launch it just like other apps
  • Completely runs when offline
  • Performance optimize using all the PWA powers with caches

I wrote a blog before to introduce PWA, now I would like to put those knowledge into action.

Zero Config PWA Plugin For Next.js

PWA is nice, but getting it to work correctly and elegantly is not that easy. I have spent a lot of time figuring out how things work under the hood and how to use workbox. Then I finally came up with an elegant solution myself, next-pwa, which allows me to add PWA support on a next.js app cleanly and easily.

PWA Support

With the plugin, add PWA is as easy as add withPWA to next.config.js

1
2
3
4
5
6
const withTypescript = require('@zeit/next-typescript')
const withPWA = require('next-pwa')

module.exports = withPWA(withTypescript({
target: 'serverless'
}))

Also, add one line in release script to copy the service worker and precache script to deployment folder. Now the web app will have full PWA support and could run offline.

One big step here is that cold start is not a problem anymore, because I use workbox to implement a pattern called Stale While Revalidate. Which return the cache copy of the web app first upon request, and send http request to server to refresh the cache content on the background.

Image from Workbox Docs

Therefore, the user only feels snapy page load instead of waiting for http request to complete fetching resources. Next time the user open the app, the refreshed cache is used, this process also eliminates the need to update the app constantly, better than native app!

Peformance

File sizes remains unchanged

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
weiwio:FWTA weiw$ ls -ohSR dist/functions/pages
total 10656
-rw-r--r-- 1 weiw 888K Apr 24 22:03 index.js
-rw-r--r-- 1 weiw 886K Apr 24 22:03 explore.js
-rw-r--r-- 1 weiw 886K Apr 24 22:03 feed.js
-rw-r--r-- 1 weiw 886K Apr 24 22:03 new.js
-rw-r--r-- 1 weiw 886K Apr 24 22:03 me.js
-rw-r--r-- 1 weiw 886K Apr 24 22:03 _error.js

weiwio:FWTA weiw$ ls -ohSR dist/public/_next/static
total 0
drwxr-xr-x 4 weiw 128B Apr 24 22:03 runtime
drwxr-xr-x 3 weiw 96B Apr 24 22:03 XU3iKTvfpizCbGajCFphN
drwxr-xr-x 3 weiw 96B Apr 24 22:03 chunks

dist/public/_next/static/runtime:
total 200
-rw-r--r-- 1 weiw 92K Apr 24 22:03 main-06c512ec64fb9631c29a.js
-rw-r--r-- 1 weiw 1.5K Apr 24 22:03 webpack-a79426b5e11f0ba5879d.js

dist/public/_next/static/XU3iKTvfpizCbGajCFphN:
total 0
drwxr-xr-x 9 weiw 288B Apr 24 22:03 pages

dist/public/_next/static/XU3iKTvfpizCbGajCFphN/pages:
total 600
-rw-r--r-- 1 weiw 241K Apr 24 22:03 _app.js
-rw-r--r-- 1 weiw 36K Apr 24 22:03 _error.js
-rw-r--r-- 1 weiw 2.3K Apr 24 22:03 index.js
-rw-r--r-- 1 weiw 1.3K Apr 24 22:03 explore.js
-rw-r--r-- 1 weiw 1.3K Apr 24 22:03 feed.js
-rw-r--r-- 1 weiw 1.3K Apr 24 22:03 me.js
-rw-r--r-- 1 weiw 1.3K Apr 24 22:03 new.js

dist/public/_next/static/chunks:
total 224
-rw-r--r-- 1 weiw 110K Apr 24 22:03 commons.635a9eee6d171762a8dc.js

Code start time is not a problem at this point.

Lighthouse report

  • Performance: 97
  • Accessibility: 63
  • Best Practices: 100
  • SEO: 100
  • PWA: 100 - Nice!

Summary

The snapshot commit could be find here.

Next

Global State Management, firebase authentication, firebase firestore …