by Gerard Sans | @gerardsans

Not a basic offline first app using
GraphQL and
Amplify DataStore



Not a basic offline first app using
GraphQL and
Amplify DataStore



SANS
GERARD
Developer Advocate AWS

Developer Advocate AWS

International Speaker

Spoken at 152 events in 37 countries
What is Offline first?

Offline First for Web
Reliable
Storage
Native-like Features
Great User Experience
Offline
Ready
Progressive Web Apps
Reach
Capabilities
Native
Applications
PWA
Applications
Web/SPA
Applications
PWA Core Requirements
Web App
Manifest
Service
Worker
Security
(HTTPS)
Service Worker Online
index.html
Cache
Hosting
Service
Worker
app.js
app.js
app.js
logo.png
logo.png
logo.png
app.js
logo.png
app.js
logo.png
Service Worker Offline
index.html
Cache
Hosting
Service
Worker
OFFLINE
app.js
logo.png
app.js
logo.png
app.js
logo.png
app.js
logo.png

AWS AMPLIFY

Fullstack Serverless
🦄
🌩️

Update
Init
Add
Push
Amplify CLI

Categories
interactions
storage
notifications
auth
analytics
function
api
hosting
xr
transcribe
translate
polly
rekognition
comprehend

Chatty


Chatty App


AppSync

GraphQL
$ amplify init
$ amplify add auth
$ amplify add api
$ amplify push
src/app.component.ts
Amplify CLI commands
type Chatty @model {
id: ID!
user: String!
message: String!
createdAt: AWSDateTime
}
src/app.component.ts
Chatty GraphQL Schema
Amplify DataStore Offline

Amplify DataStore Online


import { DataStore } from "@aws-amplify/datastore";
import { Chatty } from "./models";
await DataStore.save(new Chatty({
user: "gsans",
message: "Hi everyone!👋",
createdAt: new Date().toISOString()
}))
src/app.component.ts
Creating a Message
import { DataStore, Predicates } from "@aws-amplify/datastore";
import { Chatty } from "./models";
const msg = await DataStore.query(Chatty, Predicates.ALL);
src/app.component.ts
Querying data
Make it
a PWA!
$ vue add @vue/pwa
src/main.js (Updated)
> + import './registerServiceWorker'
src/registerServiceWorker.js (Added)
src/app.component.ts
Run PWA Vue CLI plugin
$ yarn build
src/app.component.ts
Test your PWA
└── dist
├── css
│ └── app.<version>.css
├── img/icons
│ ├── android-chrome-<size>.png
│ └── ...
├── js
│ ├── app.<version>.png
│ └── ...
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.<version>.json
├── robots.txt
└── service-worker.js
$ cd dist
/dist$ python -m SimpleHTTPServer 8887

// vue.config.js
const manifest = require('./public/manifest.json')
module.exports = {
pwa: {
name: manifest.short_name,
themeColor: manifest.theme_color,
msTileColor: manifest.background_color,
appleMobileWebAppCapable: 'yes',
appleMobileWebAppStatusBarStyle: 'black',
workboxPluginMode: 'InjectManifest',
workboxOptions: {
swSrc: 'src/service-worker.js',
}
src/app.component.ts
Add custom configuration (1/2)
// src/service-worker.js
workbox.core.setCacheNameDetails({ prefix: 'amplify-datastore' })
workbox.core.skipWaiting()
workbox.core.clientsClaim()
const cacheFiles = [{
"revision": "e653ab4d124bf16b5232",
"url": "https://aws-amplify.github.io/img/amplify.svg"
}]
self.__precacheManifest = cacheFiles.concat(self.__precacheManifest || [])
workbox.precaching.precacheAndRoute(self.__precacheManifest, {})
src/app.component.ts
Add custom configuration (2/2)
Chatty
PWA

Web, Mobile and Desktop



Add to home screen




Passes Lighthouse Test

99% Offline-ready
- Survives offline reload
- Stores messages while offline
- Shares messages when back online
- User doesn't know if App is offline
// <div v-if="offline">You are offline.</div>
// App.vue
import { Hub } from 'aws-amplify';
export default {
data() {
return { offline: undefined };
},
created() {
this.listener = Hub.listen('datastore', {payload:{event}} => {
if (event === 'networkStatus') {
this.offline = !data.active;
}
})
}
}
src/app.component.ts
Improve Offline UX

- Faster (pre-cached)
- Online/Offline
- Full screen app
- Browser/Mobile/Desktop
- Web/Native-like features
- Slower
- Online
- Tab in browser
- Browser
- Web features
Web/SPA vs PWA

Try it!
amplify-datastore-chatty-pwa-vue (solution)
amplify-datastore-chatty-vue (workshop)



Not a basic offline-first app using GraphQL and Amplify DataStore
By Gerard Sans
Not a basic offline-first app using GraphQL and Amplify DataStore
Offline-first apps need to support: intermittent connectivity, transition seamlessly between online and offline states, reliable CRUD on-device data, data synchronisation and data conflict resolution to enable real-time collaboration. Amplify DataStore is an on device persistent repository for interacting with local data and able to automatically synchronize via GraphQL. Using Amplify DataStore will allow us to implement offline-first while using a simple programming model.
- 2,848