# Offline-first

Right - we have a real-time application running, but how do we get our application to be offline-first? Well, it is very simple - in fact so simple it ought to be illegal!

First we have to import the necessary wrappers; one for the client and one for the server.

    For the server we do this

      Now restart the server and refresh the client in the browser and that's it! From now on, all activity on the messages service on the client will be handled in a client-first server-later (possibly very shortly after) manner. What's more, whenever the client has a valid connection to the server it will synchronize all changes made on the message service while offline - regardless of the origin of the changes.

      Synchronization is done in a newest change wins manner. Changing the same (same uuid) item on three different offline devices makes the latest change eventually become the winner.

      Items removed from the server cannot be revived (this is because we make a 'soft-delete' on the server to be able to ensure synchronization can be successful at all times).

      Note: For this to work you must ensure the service implements the date fields updatedAt, onServerAt, and the id field uuid. The wrapper will do all handling of the fields behind the scenes. (The uuid do not have to be the id field but it is considered good practice). You can rename these fields if you want (see Offline-first API).

      For MongoDB you do not have to worry, but for schema-centric DBs you have to ensure your schema include these fields.

      Note: If you want to know more about how the wrappers work read own-data/own-net implementation.

      # Come-on, it can't be that simple!

      Well, it almost is due to Feathers clever adapter implementation. All CRUD service adapters, that are able to pass the adapterTests, should be able work seamlessly with the realtime wrappers. But, you have to choose the wrapper to use based on your needs:

      My need own-data own-net Comment
      Keep my data in sync (✔️) ✔️ own-net is less chatty
      Every operation should be available to hooks ✔️ the only choice
      Only accumulated operations needed for hooks ✔️ own-net is less chatty

      Furthermore, you need to decide how frequent you want the automatic synchronization to be performed (default is every 24 hours).

      Last, you might consider if your application needs to synchronize outside the automatic synchronization and if that's the case you have to make sure you activate the method (with the right options, see FeathersJS Offline-first API).

      Note: The realtime wrappers are meant to be used as wrappers for database adapters and will therefore not accept app.service(<path>).update(id, ...) with id === null. You have to use patch to alter several documents at the same time.

      Tip: You should use the own-data / own-net wrappers with some care, as they consume parts of the browsers storage (either WebSQL, IndexedDB, or localStorage) which is not an unlimited resource pool.

      Tip: If you want to take advantage of the own-data / own-net for your server backends, then you must include a localStorage solution before you include @feathersjs-offline/client like:

      let LocalStorage = require('node-localstorage').LocalStorage;
      global.localStorage = new LocalStorage('./.scratch');
      

      and of cause use @feathersjs-offline/server for the master server.

      # What's next?

      In the final chapter, we'll look at how to write automated tests for our API. Alternatively, you can digress a read about how Feathers Offline-first has been implemented.

      Anything unclear or missing? Get help (opens new window) or Edit this page (opens new window)

      Last Updated: 7/30/2021, 5:01:58 PM