Apollo-Offline は、Apollo GraphQL クライアントを使用したシームレスなオフラインファーストのアプリ開発を可能にするカスタム ネットワーク インターフェイスと Redux ストア エンハンサーを提供します。
Apollo-Offline は Redux-Offline の上に構築されています (したがって、その機能はすべて継承されています)。
Apollo の既存のオフライン (っぽい) 機能 (組み込みのキャッシュや突然変異に対する楽観的な応答など) を利用することを目的としています。これは、移行時にコードを大幅に変更する必要がないことを意味します (これらの機能をすでに使用している限り)。
Apollo-Offline を使用すると、クエリとミューテーションのコードは、Apollo-Offline を使用しない場合とまったく同じように見えます。
これには例外が 1 つあります。それは、 「オプティミスティックフェッチ」機能です。
「オプティミスティックフェッチ」が行うことは、最初にキャッシュからクエリの応答を読み取ろうとすることですが、ネットワーク接続が利用可能な場合に限り、バックグラウンドでサーバーの応答を取得し、それをキャッシュに書き込みます(その時点で)。たとえば、ラップされた React コンポーネントは 2 回目に更新されます)。
基本的に、これは、要求されたデータがローカル キャッシュにある場合は UI のクエリが常に機能し、キャッシュされたデータに到達できる場合は常にキャッシュされたデータとサーバー データの一貫性が保たれることを意味します。
注: 私の意見では、これはfetchPolicy: 'cache-and-network'
が行うべきことです (しかし、そうではありません。サーバーにアクセスできない場合はエラーになります)。
これを有効にするには、真の値を持つ__offline__
フィールドをその特定のクエリのクエリ変数 (つまり、 variables: { __offline__: true }
) に追加します。
詳しい手順については、以下の例を参照してください。
糸を使って
yarn add apollo-offline
またはnpm
npm install --save apollo-offline
Apollo-Offline では、さらに次のピア依存関係をインストールする必要があります。
apollo-client
redux
import { ApolloClient , createNetworkInterface } from 'apollo-client' ;
import { applyMiddleware , combineReducers , compose , createStore } from 'redux' ;
import config from '@redux-offline/redux-offline/lib/defaults' ;
import offline from 'apollo-offline' ;
// 1. Wrap your network interface
const { enhancer , networkInterface } = offline (
createNetworkInterface ( {
uri : `http://localhost` ,
} ) ,
) ;
// 2. Create your Apollo client
const client = new ApolloClient ( {
/* Your Apollo configuration here... */
networkInterface ,
} ) ;
// 3. Pass the client to the offline network interface
// (Optional, but needed for the optimistic fetch feature)
networkInterface . setClient ( client ) ;
// 4. Create your redux store
export const store = createStore (
combineReducers ( {
apollo : client . reducer ( ) ,
} ) ,
undefined ,
compose (
applyMiddleware ( client . middleware ( ) ) ,
// Apply offline store enhancer
// (You can pass your own redux-offline config, but the default one is a good starting point)
enhancer ( config ) ,
) ,
) ;
注: セットアップが完了すると、apollo-offline はすべてのクエリ/ミューテーションをインターセプトして、シームレスなオフラインファーストの動作を有効にします。
ここから一部のクエリ/ミューテーションを選択的に除外したい場合は、真の値を持つ__online__
フィールドをその特定のクエリ/ミューテーションのクエリ変数 (つまり、 variables: { __online__: true }
) に追加することで、Apollo のデフォルトの動作に戻すことができます。 。
/* Setup goes here... */
// Queries
client . query ( { query : /* Your query here */ } ) ;
// - Using optimistic fetch feature
client . query ( {
fetchPolicy : 'network-only' ,
query : /* Your query here */ ,
variables : {
__offline__ : true , // Enable optimistic fetch
} ,
} ) ;
// Mutations
client . mutate ( {
mutation : /* Your mutation here */ ,
optimisticResponse : /* Your optimistic response here */ ,
update : /* Your update resolver here */ ,
} ) ;
エントリポイントで:
/* Setup goes here... */
import { ApolloProvider } from 'react-apollo' ;
import { connect } from 'react-redux' ;
import App from './App' ; // Your main application component
// Component to postpone render until after Redux state has been rehydrated
const Rehydrated = connect ( ( { rehydrated } ) => ( { rehydrated } ) )
( ( props ) => props . rehydrated ? props . children : props . loading ) ;
const Loading = ( ) => < div > Loading... </ div > ;
ReactDOM . render (
< ApolloProvider client = { client } store = { store } >
< Rehydrated loading = { < Loading /> } >
< App />
</ Rehydrated >
</ ApolloProvider > ,
document . getElementById ( 'root' ) ,
) ;
コンポーネントをラップする場合:
import React from 'react' ;
import { graphql } from 'react-apollo' ;
// Queries
const wrappedComponent = graphql ( /* Your query here */ ) ( /* Your component here */ ) ;
// - Using optimistic fetch feature
const wrappedComponent = graphql (
/* Your query here */ ,
{
options : {
fetchPolicy : 'network-only' ,
variables : {
__offline__ : true , // Enable optimistic fetch
} ,
} ,
} ,
) ( /* Your component here */ ) ;
// Mutations (you will want to provide an optimistic response when executing them)
const wrappedComponent = graphql (
/* Your mutation here */ ,
{
options : {
update : /* Your update resolver here */ ,
} ,
} ,
) ( /* Your component here */ ) ;
リポジトリのクローンを作成した後に行うことは次のとおりです。
yarn / npm install
(依存関係をインストールします)
TSLintの実行
npm run lint
lint エラーを自動的に修正してみる
npm run lint:fix
次を使用して Jest 単体テストを実行します。
npm test
npm run test:coverage
テストは、モジュールが存在するのと同じディレクトリで定義されます。テストは、「[モジュール].test.js」ファイルで指定されます。
プロジェクトをビルドするには、次のコマンドを実行します。
npm run build
これにより、本番環境に対応したコードが「dist/」に保存されます。