Offline toolkit for Apollo
Apollo-Offline provides a custom network interface and Redux store enhancer that enable seamless offline-first app development using the Apollo GraphQL client.
Apollo-Offline is built on top Redux-Offline (and thus inherits all of is features).
It aims to make use of Apollo's existing offline(-ish) features (e.g. built-in caching and optimistic responses for mutations). This means when migrating, your code won't have to change a lot (as long as you are already using these features).
With Apollo-Offline, the code of your queries and mutations looks exactly like it would without.
There is one exception to this: The "optimistic fetch" feature.
Optimistic Fetch
What "optimistic fetch" does is it tries to first read a query's response from the cache, but if (and only if!) a network connection is available will get the server's response in the background and write it to the cache (at that point e.g. wrapped React components will update a second time).
Basically this means your UI's queries will always work if the requested data is available in the local cache and it will always keep the cached data consistent with your server data if it can be reached.
Note: In my opinion, this is what fetchPolicy: 'cache-and-network'
should do (but doesn't - it errors if the server can't be reached).
To enable it, add an __offline__
field with a truthy value to the query variables of that specific query (i.e. variables: { __offline__: true }
).
For further instructions, see the examples below.
Install
using yarn
yarn add apollo-offline
or npm
npm install --save apollo-offline
Apollo-Offline additionally requires you to have the following peer dependencies installed:
apollo-client
redux
Usage (Examples)
Setup
;;; ; // 1. Wrap your network interfaceconst enhancer networkInterface = ; // 2. Create your Apollo clientconst client = /* Your Apollo configuration here... */ networkInterface; // 3. Pass the client to the offline network interface// (Optional, but needed for the optimistic fetch feature)networkInterface; // 4. Create your redux storeconst store = ;
Note: Once set up, apollo-offline intercepts all queries/mutations to enable its seamless offline-first behaviour.
If you want to selectively exclude some queries/mutations from this, you can revert back to Apollo's default behaviour by adding an __online__
field with a truthy value to the query variables of that specific query/mutation (i.e. variables: { __online__: true }
).
Vanilla JS
/* Setup goes here... */ // Queriesclient; // - Using optimistic fetch featureclient; // Mutationsclient;
React
In your entry point:
/* Setup goes here... */ ;; ; // Your main application component // Component to postpone render until after Redux state has been rehydratedconst Rehydrated = propsrehydrated ? propschildren : propsloading; const Loading = <div> Loading... </div>; ReactDOM;
When wrapping your components:
;; // Queriesconst wrappedComponent = /* Your component here */; // - Using optimistic fetch featureconst wrappedComponent = /* Your component here */; // Mutations (you will want to provide an optimistic response when executing them)const wrappedComponent = /* Your component here */;
Developing
This is what you do after you have cloned the repository:
yarn / npm install
(Install dependencies)
Linting
Execute TSLint
npm run lint
Try to automatically fix linting errors
npm run lint:fix
Testing
Execute Jest unit tests using
npm test npm run test:coverage
Tests are defined in the same directory the module lives in. They are specified in '[module].test.js' files.
Building
To build the project, execute
npm run build
This saves the production ready code into 'dist/'.