Skip to content

Instantly share code, notes, and snippets.

@meagar
Last active August 14, 2018 09:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save meagar/9600625 to your computer and use it in GitHub Desktop.
Save meagar/9600625 to your computer and use it in GitHub Desktop.
Taking JavaScript Offline

Note: this presentation was written for Gistdeck. Add the bookmarklet, come back to this gist, click the bookmarklet, then use the arrow keys to navigate.

Note2: See https://github.com/meagar/taking-javascript-offline for code examples; any time a string like 2-basic-caching appears, that's a branch which supports that slide

Taking JavaScript Offline

Who am I?

@meagar

Matthew Eagar / Tech Lead / 500px

Case Study

Data Capture

  • Survey consumers on the street
  • Take photos, capture signatures
  • On Windows, IOS, Android devices
  • Sync to central data store (Rails)
  • With no wifi or cell network

Solution?

Native App

Three Native Apps

PhoneGap

HTML5!

HTML5

  • Appcache
  • IndexedDB
  • Location
  • WebSockets
  • FileReader

HTML5

Store site structure in appcache

RESTful API for data

Temporary storage in IndexedDB

It worked!

CODE BREAK

  • Sample Backbone app
  • Basic RESTful API
  • JS + Coffee + EJS + Jade?

1-no-cache

Appcache

A mechanism for storing/accessing static assets offline

  • Driven by manifests

  • Define paths to cache

    • JS/CSS/images/HTML
  • Full of gotchas

  • 5mb limit

Appcache isn't...

A douche bag :(

poor appcache

Basic caching

manifests...

  • Contain sections, paths, comments
  • included via <html manifest="...">
  • Served with Content-type: text/appcache *
  • Have a .appcache extension *
  • start with CACHE MANIFEST

Basic caching

CACHE MANIFEST

CACHE:
# Static assets
/js/jquery.js
/js/app.js
/css/bootstrap.css
/css/styles.css

# Single-page backbone apps
/posts
/users

Basic caching

<!doctype html>
<html manifest="/my_cache.appcache">
<head>
  <script src="/js/jquery.js"></script>
  <!-- ... -->

More code!

Add a basic manifest

Hooray for Chrome!

2-basic-caching

Gotcha #1

Once appcache'd, content only comes from appcache

Gotcha #2

On cached pages, all requests go through Appcache

client-server-1

Gotcha #2

On cached pages, all requests go through Appcache

client-server-1

Gotcha #3

Appcache only updates if the manifest changes

Gotcha #4

Request that triggers an update still comes from appcache

Changes require two page reloads to become apparent

So...

On cached pages, all requests go through Appcache

client-server-1

So...

On cached pages, all requests go through Appcache

client-server-2

NETWORK sections

Appcache allows NETWORK sections to define content that shouldn't be cached

NETWORK sections

CACHE MANIFEST

CACHE:

# Single-page backbone apps
/posts
/users

NETWORK:
/api/posts

2-basic-cache

Tiny Gotcha #...5?

Implicit Caching

You can't NETWORK a page which has a manifest; it's cached implicitly

Going offline

Some content can't/shouldn't be cached

FALLBACK lets us provide defaults for use while offline

FALLBACK:
# Don't show user profiles while offline
/users/* /offline

Aside: Going offline

Our SPA can detect the presence of a network connection and render accordingly

navigator.onLine // true/false
window.addEventListener('online', fn);
window.addEventListener('offline', fn);

3-going-offline

Dealing with realistic network conditions

Networks are slow

The appcache doesn't like slow networks

4-waiting-on-appcache

Gotcha #6

Manifest downloads are brittle

  • Entire manifest is redownloaded
  • Upgrade is interruptable
  • Users unaware that updates are happening
  • Errors cancel entire update

Appcache events

Appache emits several useful events

Can tie into them to provide a GUI for updates

Appcache events

First load:

  • checking
  • downloading
  • progress(, progress, ...)
  • cached

Appcache events

Subsequent loads

  • checking
  • noupdate
  • downloading
  • progress(, progress, ...)
  • cached

Building a dedicated updater!

More code!

  • Detect cache downloading
  • Show progress

4-waiting-on-appcache

Appcache Obsoletion

Allows programatic expiration of the entire cache

Still subject to the double-reload requirement

Forces browser into uncached state

5-obsoletion

Gotcha #lots

Obsolete caches!

Why obsoletion instead of updating?

Why obsoletion?

  • /login - online only, set is_authorized

  • /index - offline

    • check is_authorized
      • bounce to index
  • /login - change to auth_token

What should I appcache?

Static sites for mobile!

Web apps that server structure first, data later

Anything!

That's the appcache!

IndexedDB

IndexedDB

Very quickly...

  • A key/value store
  • larger than localStorage
  • Size varies from browser-to-browser
  • Prompts the user for more storage

IndexedDB

Very quickly...

  • Doesn't warn you when it's full *
  • Supports transactions, migrations, indices
  • Faster than you might expect, slower than you might hope

IndexedDB

Behavies like REST:

Backbone.sync

IndexedDB

backbone-indexeddb.js

6-indexeddb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment