GA Calc
About
A small PWA to determine gestational age based on mean sac diameter.
I made this app to explore the PWA space, get familiar with the offline capabilities afforded by ServiceWorkers, and to pursue a perfect 100 across all Lighthouse audits - which I have
Building the repo
To begin, clone the repo and open the directory
$ git clone https://github.com/chrstntdd/ga-calc.git && cd ga-calc
Then install the project dependencies
$ yarn install
Start the development server
$ yarn start
Finally, open your browser to http://localhost:8080/
to view the app
Technology
Build process
As stated above, for development, webpack-dev-server
does all the heavy lifting for us.
For production, the process is a bit more involved to squeeze out every last drop of performance.
First, we transpile our src
files to the build
folder at the root of the project. The output is plain JS, compiled by Babel, mirroring our src
directory.
Next, we run webpack
in production mode, writing to the dist
folder at the root
. This directory will contain the index.html
, JavaScript in js/**
and the CSS in css/**
.
Following that, there are some custom scripts (scripts/build.ts
) that use the output of the previous two steps to bring it all together.
At a high level, the build script is responsible for the following:
- Adding
link
rel="preload"
tags to the head ofindex.html
- Adding
script
tags toindex.html
- Inlining the small webpack runtime chunk into
index.html
- Inlining critical CSS into the head of
index.html
- Minifying
index.html
- Copying the contents of
src/assets
todist/images
- Moving the pre-compiled
service-worker.js
file todist/sw.js
& adding in the correct file names of the emitted assets that have to be pre-cached (the JS modules, webmanifest, and theindex.html
page itself). - Minifying the newly created
dist/sw.js
file
Todo
- Input validation? (
inputMode="decimal"
seems to work well enough) - Smooth out ServiceWorker integration
- Offline messaging
- Update messaging
- Integrate w/ build process
- Pre-render? (work out bugs w/ hydrating inputs and using persisted
localStorage
state) - Tests 😅
- Differential serving