يوفر Apollo-Offline واجهة شبكة مخصصة ومُحسِّن متجر Redux الذي يتيح التطوير السلس للتطبيق دون اتصال أولاً باستخدام عميل Apollo GraphQL.
تم إنشاء Apollo-Offline فوق Redux-Offline (وبالتالي يرث جميع ميزاته).
ويهدف إلى الاستفادة من ميزات Apollo غير المتصلة بالإنترنت (-ish) (مثل التخزين المؤقت المدمج والاستجابات المتفائلة للطفرات). وهذا يعني أنه عند الترحيل، لن يلزم تغيير التعليمات البرمجية الخاصة بك كثيرًا (طالما أنك تستخدم هذه الميزات بالفعل).
باستخدام Apollo-Offline، يبدو رمز استعلاماتك وتحولاتك تمامًا كما لو كان بدونها.
هناك استثناء واحد لهذا: ميزة "الجلب المتفائل" .
ما يفعله "الجلب المتفائل" هو أنه يحاول أولاً قراءة استجابة الاستعلام من ذاكرة التخزين المؤقت، ولكن في حالة توفر اتصال بالشبكة (وفقط في حالة!) سيحصل على استجابة الخادم في الخلفية ويكتبها في ذاكرة التخزين المؤقت (في تلك المرحلة على سبيل المثال، سيتم تحديث مكونات React الملتفة مرة ثانية).
يعني هذا بشكل أساسي أن استعلامات واجهة المستخدم الخاصة بك ستعمل دائمًا إذا كانت البيانات المطلوبة متوفرة في ذاكرة التخزين المؤقت المحلية وستحتفظ دائمًا بالبيانات المخزنة مؤقتًا متسقة مع بيانات الخادم الخاص بك إذا كان من الممكن الوصول إليها.
ملاحظة: في رأيي، هذا هو ما يجب أن يفعله fetchPolicy: 'cache-and-network'
(لكنه لا يفعل ذلك - فهو يخطئ إذا تعذر الوصول إلى الخادم).
لتمكينه، قم بإضافة حقل __offline__
بقيمة صحيحة إلى متغيرات الاستعلام الخاصة بهذا الاستعلام المحدد (أي variables: { __offline__: true }
).
لمزيد من التعليمات، راجع الأمثلة أدناه.
باستخدام الغزل
yarn add apollo-offline
أو نبم
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 جميع الاستعلامات/الطفرات لتمكين سلوكه السلس دون الاتصال بالإنترنت أولاً.
إذا كنت تريد استبعاد بعض الاستعلامات/الطفرات بشكل انتقائي من هذا، فيمكنك العودة مرة أخرى إلى سلوك Apollo الافتراضي عن طريق إضافة حقل __online__
بقيمة صحيحة إلى متغيرات الاستعلام الخاصة بهذا الاستعلام/الطفرة المحددة (أي variables: { __online__: true }
) .
/* 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
حاول إصلاح أخطاء الفحص تلقائيًا
npm run lint:fix
تنفيذ اختبارات وحدة Jest باستخدام
npm test
npm run test:coverage
يتم تعريف الاختبارات في نفس الدليل الذي تعيش فيه الوحدة. ويتم تحديدها في ملفات '[module].test.js'.
لبناء المشروع، تنفيذ
npm run build
يؤدي هذا إلى حفظ كود الإنتاج الجاهز في "dist/".