全解讀:從 4.0 架構(gòu)重構(gòu)到 4.2 類(lèi)型安全與事件驅(qū)動(dòng) Refetch)
Apollo Client 版本演進(jìn)全解讀從 4.0 架構(gòu)重構(gòu)到 4.2 類(lèi)型安全與事件驅(qū)動(dòng) Refetch【免費(fèi)下載鏈接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ap/apollo-client這篇技術(shù)指南以倉(cāng)庫(kù)根目錄的 CHANGELOG.md覆蓋 Apollo Client 2.3.2 至 4.2.12 的全部版本記錄為核心脈絡(luò)系統(tǒng)梳理 Apollo Client 4.x 系列帶來(lái)的架構(gòu)級(jí)變革框架無(wú)關(guān)核心、統(tǒng)一錯(cuò)誤處理、dataState結(jié)果狀態(tài)、可插拔增量交付、classic/modern 雙簽名類(lèi)型系統(tǒng)以及 4.2 全新引入的事件驅(qū)動(dòng)自動(dòng) RefetchRefetchEventManager。讀完本文你將理解每個(gè)版本為什么改、改了什么、如何遷移并能直接對(duì)照倉(cāng)庫(kù)源碼src/core、src/errors、src/incremental、src/local-state等驗(yàn)證底層實(shí)現(xiàn)。一、CHANGELOG 覆蓋范圍與閱讀方法當(dāng)前倉(cāng)庫(kù)的 CHANGELOG.md 是一份累計(jì)超過(guò) 1 萬(wàn)行的完整版本歷史覆蓋從 2018 年的2.3.2到當(dāng)前最新的4.2.124.2.x 系列最新的補(bǔ)丁與次要版本當(dāng)前頭部包含類(lèi)型系統(tǒng)現(xiàn)代化與事件驅(qū)動(dòng) Refetch 兩大主線(xiàn)4.0.0 大版本一次完整的架構(gòu)重構(gòu)文內(nèi)含獨(dú)立的Release Notes專(zhuān)題章節(jié)見(jiàn) CHANGELOG.md 4.0.0 一節(jié)是理解現(xiàn)代 Apollo Client 設(shè)計(jì)哲學(xué)的核心材料3.x / 2.x 系列早期歷史記錄了大量緩存、ObservableQuery、fetch policy 相關(guān)的修復(fù)對(duì)排查歷史問(wèn)題仍有參考價(jià)值。版本條目統(tǒng)一采用 Changesets 格式每個(gè)條目包含 PR 鏈接、提交哈希、貢獻(xiàn)者與變更說(shuō)明并用### Minor Changes新特性與### Patch Changes修復(fù)分類(lèi)。下文聚焦最有價(jià)值的 4.x 主線(xiàn)展開(kāi)。二、Apollo Client 4.0一次徹底的架構(gòu)重構(gòu)4.0.0 的 Release Notes 明確將其定位為更現(xiàn)代、更高效、更類(lèi)型安全的 GraphQL 客戶(hù)端體驗(yàn)核心圍繞開(kāi)發(fā)者體驗(yàn)、包體積優(yōu)化與框架靈活性三個(gè)方向。2.1 框架無(wú)關(guān)的核心Framework-Agnostic Core4.0 將 React 功能與核心庫(kù)分離React 相關(guān)導(dǎo)出統(tǒng)一收歸apollo/client/react核心不再依賴(lài) React。這意味著你可以在任意 JavaScript 框架中使用 Apollo Client 而不會(huì)引入 React 依賴(lài)。倉(cāng)庫(kù)中 src/react/index.ts 與 src/core/ApolloClient.ts 的目錄劃分正是這一架構(gòu)的落地體現(xiàn)。2.2 更小的包體積局部狀態(tài)按需引入client指令能力改為通過(guò)LocalState類(lèi)按需啟用源碼見(jiàn) src/local-state/LocalState.ts不使用局部狀態(tài)時(shí)不會(huì)被打包現(xiàn)代構(gòu)建目標(biāo)轉(zhuǎn)譯目標(biāo)為since 2023, node 20, not dead充分利用現(xiàn)代 JavaScript 特性更優(yōu)的 Tree-Shakingpackage.json中規(guī)范的exports字段讓死代碼消除更徹底。2.3 統(tǒng)一錯(cuò)誤處理Unified Error Handling4.0 移除了ApolloError改用一組更細(xì)粒度的錯(cuò)誤類(lèi)并統(tǒng)一收斂到單一的error屬性錯(cuò)誤類(lèi)語(yǔ)義CombinedGraphQLErrors服務(wù)器返回的 GraphQL 錯(cuò)誤源碼見(jiàn) src/errors/CombinedGraphQLErrors.tsServerError非 GraphQL 的服務(wù)器錯(cuò)誤ServerParseError服務(wù)器響應(yīng)解析錯(cuò)誤UnconventionalError非 Error 對(duì)象被 throw 時(shí)的包裝LinkError鏈路Link拋出的錯(cuò)誤通過(guò).is()判定這些類(lèi)都提供靜態(tài).is()方法用于類(lèi)型收窄網(wǎng)絡(luò)錯(cuò)誤也遵循errorPolicy設(shè)置外部錯(cuò)誤則原樣透?jìng)鞑辉侔b。遷移示例// Apollo Client 3 if (error instanceof ApolloError) { console.log(error.graphQLErrors); console.log(error.networkError); } // Apollo Client 4 import { CombinedGraphQLErrors } from apollo/client; if (CombinedGraphQLErrors.is(error)) { console.log(error.errors); // GraphQL errors } else if (error) { console.log(error.message); // Other errors }2.4 全新的dataState屬性dataState清晰標(biāo)識(shí)查詢(xún)結(jié)果的完整性是 4.0 類(lèi)型系統(tǒng)的基石之一empty無(wú)數(shù)據(jù)data為undefinedpartialreturnPartialData為true時(shí)從緩存讀到的部分?jǐn)?shù)據(jù)streamingdefer查詢(xún)?nèi)栽诹魇椒祷刂械牟煌暾麛?shù)據(jù)complete完全滿(mǎn)足的查詢(xún)結(jié)果。const { data, dataState } useQuery(MY_QUERY); if (dataState complete) { // TypeScript 知道 data 字段是完整的 console.log(data.allFields); } else if (dataState partial) { // TypeScript 知道 data 可能缺字段 console.log(data?.someField); }2.5 可插拔的增量交付defer/stream4.0 將增量交付設(shè)計(jì)為可配置、面向未來(lái)的機(jī)制通過(guò)incrementalHandler注入。倉(cāng)庫(kù)中的導(dǎo)出見(jiàn) src/incremental/index.tsimport { Defer20220824Handler } from apollo/client/incremental; const client new ApolloClient({ // ... incrementalHandler: new Defer20220824Handler(), });NotImplementedHandler默認(rèn)處理器一旦使用defer直接拋出異常Defer20220824Handler支持 Apollo Router 的增量格式同時(shí)以GraphQL17Alpha2Handler別名導(dǎo)出。2.6 局部狀態(tài)管理LocalState 類(lèi)client字段解析改為顯式啟用import { LocalState } from apollo/client/local-state; const client new ApolloClient({ cache, localState: new LocalState({ resolvers: { Query: { myField: () Hello World, }, }, }), });同時(shí) resolver 的context結(jié)構(gòu)發(fā)生變化4.0 中context提供client、requestContext、phase三個(gè)字段cache改為通過(guò)client.cache獲取// Apollo Client 4 const resolver (parent, args, context, info) { const { client, requestContext, phase } context; const cache client.cache; };2.7 React 側(cè)改進(jìn)useLazyQuery重構(gòu)不再接受variables/context選項(xiàng)改由execute接收execute只接受variables與context禁止在渲染期間或 SSR 中調(diào)用新查詢(xún)啟動(dòng)時(shí)自動(dòng)取消在途查詢(xún)useMutation移除ignoreResults選項(xiàng)如需 fire-and-forget 直接使用client.mutateuseQuerynotifyOnNetworkStatusChange默認(rèn)改為true移除廢棄的onCompleted/onError回調(diào)新 SSR APIprerenderStatic取代舊的 SSR 函數(shù)支持 React 19 的 prerender APIimport { prerenderStatic } from apollo/client/react/ssr; const html await prerenderStatic(App /, { client, });React Compiler 支持提供apollo/client/react/compiled入口見(jiàn) src/react/index.ts 中 compiled 運(yùn)行時(shí)內(nèi)置 React 17 兼容的運(yùn)行時(shí) polyfill。2.8 Link 體系演進(jìn)全部類(lèi)化創(chuàng)建函數(shù)creator function統(tǒng)一遷移為類(lèi)// Apollo Client 3 import { createHttpLink, setContext } from apollo/client; const httpLink createHttpLink({ uri: /graphql }); const authLink setContext((operation, prevContext) { /*...*/ }); // Apollo Client 4 import { HttpLink, SetContextLink } from apollo/client; const httpLink new HttpLink({ uri: /graphql }); const authLink new SetContextLink((prevContext, operation) { /*...*/ });ErrorLink也同步改為單一error屬性與錯(cuò)誤類(lèi).is()判定對(duì)應(yīng)倉(cāng)庫(kù) src/link/error/index.ts。2.9 遷移工具與破壞性變更清單4.0 提供自動(dòng)化 codemod# 基礎(chǔ)用法 npx apollo/client-codemod-migrate-3-to-4 src # TypeScript 項(xiàng)目分開(kāi)執(zhí)行 npx apollo/client-codemod-migrate-3-to-4 --parser ts --extensions ts src npx apollo/client-codemod-migrate-3-to-4 --parser tsx --extensions tsx srccodemod 依次處理導(dǎo)入更新React 導(dǎo)入遷往apollo/client/react→ 類(lèi)型遷移遷往新的命名空間位置→ Link 更新創(chuàng)建函數(shù)轉(zhuǎn)類(lèi)→ 被移除導(dǎo)出的處理遷往apollo/client/v4-migration。關(guān)鍵的破壞性變更對(duì)應(yīng)倉(cāng)庫(kù) src/core/ApolloClient.ts 的構(gòu)造函數(shù)包括安裝rxjs成為 peer dependency安裝命令為npm install apollo/client graphql rxjs構(gòu)造函數(shù)link變?yōu)楸靥畈辉匐[式創(chuàng)建HttpLinkuri/headers/credentials移除改用HttpLinkname/version移入clientAwarenessresolvers移入LocalState構(gòu)造器connectToDevTools換成devtools.enableddisableNetworkFetches更名為prioritizeCacheValues類(lèi)型系統(tǒng)移除TContext、TCacheShape泛型類(lèi)型遷入命名空間自定義 context 改走模塊增強(qiáng)Observable從zen-observable遷移到 RxJS轉(zhuǎn)換必須調(diào)用.pipe()使用 RxJS 操作符測(cè)試MockedProvider默認(rèn)帶真實(shí)延遲20–50ms移除createMockClient改用MockLink性能與構(gòu)建不再為現(xiàn)代特性降級(jí)轉(zhuǎn)譯、不內(nèi)置 polyfill、開(kāi)發(fā)模式通過(guò) export conditions 控制、完善的exports字段與 source maps移除的導(dǎo)出React render-prop 組件apollo/client/react/components、HOCapollo/client/react/hoc、apollo/client/react/parser、apollo/client/utilities/globals。官方建議的升級(jí)路徑先升到 3.14 收集廢棄警告 → 安裝rxjs→ 運(yùn)行 codemod → 更新ApolloClient初始化顯式HttpLink、按需LocalState→ 重寫(xiě)錯(cuò)誤處理 → 重點(diǎn)回歸 SSR、錯(cuò)誤處理與局部狀態(tài)。三、Apollo Client 4.1增量交付與 Fragment 觀察能力增強(qiáng)4.1.0 在 4.0 基礎(chǔ)上繼續(xù)強(qiáng)化增量交付與緩存觀察 APIGraphQL17Alpha9Handler支持graphql17.0.0-alpha.9實(shí)現(xiàn)的更新版defer增量格式源碼見(jiàn) src/incremental/handlers/graphql17Alpha9.ts。注意只有服務(wù)器實(shí)現(xiàn)了新版格式時(shí)才應(yīng)使用它Apollo Router 用戶(hù)應(yīng)繼續(xù)使用Defer20220824Handlerimport { GraphQL17Alpha9Handler } from apollo/client/incremental; const client new ApolloClient({ incrementalHandler: new GraphQL17Alpha9Handler(), });該處理器會(huì)把a(bǔ)ccept頭更新為multipart/mixed;incrementalSpecv0.2以請(qǐng)求最新格式。stream支持Defer20220824Handler與GraphQL17Alpha2Handler均可處理stream指令默認(rèn)只在最后一個(gè) chunk 時(shí)截?cái)鄐tream數(shù)組且僅當(dāng)結(jié)果攜帶 stream 信息時(shí)才使用默認(rèn)流式 merge 函數(shù)。Fragment 觀察增強(qiáng)useFragment/useSuspenseFragment/client.watchFragmentfrom支持?jǐn)?shù)組一次觀察多個(gè)實(shí)體data按索引對(duì)應(yīng)from數(shù)組from: null時(shí)結(jié)果固定為{ data: null, dataState: complete, complete: true }返回的 Observable 新增getCurrentResult()方法相同 fragment、變量與標(biāo)識(shí)符的 watch 會(huì)去重并盡量復(fù)用已有 Observable 以提升性能。緩存寫(xiě)入增強(qiáng)cache.write/cache.writeQuery/client.writeQuery新增extensions選項(xiàng)使 GraphQL 操作的extensions在 merge 函數(shù)中可用源碼參見(jiàn) src/cache 相關(guān)實(shí)現(xiàn)InMemoryCache不再過(guò)濾read函數(shù)顯式返回的undefined數(shù)組項(xiàng)readFragment/watchFragment/updateFragment全面支持from選項(xiàng)。client字段行為修正定義了read函數(shù)時(shí)不再把回退值強(qiáng)制設(shè)為null而是以existing undefined調(diào)用readLocalState在無(wú) resolver 且緩存無(wú)法解析client字段resolvesClientField返回false時(shí)才警告并設(shè)null。四、Apollo Client 4.2雙簽名類(lèi)型系統(tǒng)與事件驅(qū)動(dòng) Refetch4.2.0 是本倉(cāng)庫(kù)當(dāng)前版本主線(xiàn)中最具革新意義的一次次要版本包含兩個(gè)重量級(jí)特性。4.14.2 classic 與 modern 雙簽名Signature Styles4.2 為方法與 hooks 引入兩種簽名風(fēng)格Classic signatures默認(rèn)與 4.2 之前完全一致保持向后兼容支持手寫(xiě) TypeScript 泛型如useSuspenseQueryMyData(...)。但官方明確建議改用TypedDocumentNode讓類(lèi)型自動(dòng)推斷Modern signatures自動(dòng)把聲明的defaultOptions納入返回類(lèi)型類(lèi)型更準(zhǔn)確從文檔節(jié)點(diǎn)推斷類(lèi)型不支持手動(dòng)傳泛型參數(shù)傳入會(huì)產(chǎn)生類(lèi)型錯(cuò)誤。方法/鉤子會(huì)在DeclareDefaultOptions中聲明了任意非可選屬性時(shí)全局自動(dòng)切換到 modern 簽名// apollo.d.ts import apollo/client; declare module apollo/client { namespace ApolloClient { namespace DeclareDefaultOptions { interface WatchQuery { errorPolicy: all; // 非可選 → 自動(dòng)激活 modern 簽名 } } } }也可以不聲明defaultOptions、直接手動(dòng)切換到 modern 簽名或聲明后手動(dòng)切回 classic 用于遷移不推薦長(zhǎng)期使用因?yàn)闀?huì)導(dǎo)致類(lèi)型與運(yùn)行時(shí)不一致// apollo.d.ts import apollo/client; declare module apollo/client { export interface TypeOverrides { signatureStyle: modern; // 或 classic } }4.2 defaultOptions 類(lèi)型安全必須全局登記從 4.2 開(kāi)始某些defaultOptions類(lèi)型必須全局登記否則ApolloClient構(gòu)造會(huì)直接報(bào) TypeScript 錯(cuò)誤。可登記的鍵包括WatchQuery的errorPolicy與returnPartialData、Query與Mutate的errorPolicy。// apollo.d.ts import apollo/client; declare module apollo/client { namespace ApolloClient { namespace DeclareDefaultOptions { interface WatchQuery { errorPolicy: all; } interface Query { errorPolicy: all; } interface Mutate { errorPolicy: all; } } } }登記后useSuspenseQuery(MY_QUERY)的data類(lèi)型會(huì)從TData自動(dòng)變?yōu)門(mén)Data | undefined與發(fā)生錯(cuò)誤時(shí)data可能為undefined的運(yùn)行時(shí)行為保持一致單次調(diào)用顯式傳errorPolicy: none又會(huì)把data收窄回TData。若同一應(yīng)用存在多個(gè)defaultOptions沖突的客戶(hù)端實(shí)例可用聯(lián)合類(lèi)型放寬約束declare module apollo/client { export namespace ApolloClient { export namespace DeclareDefaultOptions { interface WatchQuery { errorPolicy?: none | all | ignore; returnPartialData?: boolean; } } } }代價(jià)是返回類(lèi)型會(huì)變得更泛化把屬性設(shè)為可選errorPolicy?:等價(jià)于在聯(lián)合類(lèi)型中加入 TypeScript 默認(rèn)值none。僅使用部分取值時(shí)建議聲明精確的必選聯(lián)合如errorPolicy: all | ignore以保持簽名收窄。4.3 類(lèi)型安全擴(kuò)展到 mutate 與 preloadQueryclient.mutate/useMutationerrorPolicy現(xiàn)在流入結(jié)果類(lèi)型對(duì)應(yīng)倉(cāng)庫(kù) src/core/types.ts 中ApolloClient.MutateResultnone→{ data: TData; error?: never }all→{ data: TData | undefined; error?: ErrorLike }ignore→{ data: TData | undefined; error?: never }。聲明DeclareDefaultOptions.Mutate.errorPolicy后hooks 與方法返回類(lèi)型隨之收窄單次調(diào)用顯式傳errorPolicy可覆蓋默認(rèn)值。preloadQuery來(lái)自createQueryPreloaderDeclareDefaultOptions.WatchQuery的默認(rèn)值會(huì)正確作用于PreloadedQueryRef的 data states例如聲明errorPolicy: all后preloadQuery(QUERY)返回PreloadedQueryRefTData, TVariables, complete | streaming | empty。4.4 事件驅(qū)動(dòng)自動(dòng) RefetchRefetchEventManager4.2 通過(guò)RefetchEventManager類(lèi)實(shí)現(xiàn)基于事件的自動(dòng) refetch如窗口聚焦window focus與網(wǎng)絡(luò)重連。核心實(shí)現(xiàn)見(jiàn) src/core/RefetchEventManager.ts內(nèi)置事件源為 src/core/refetchSources/windowFocusSource.ts 與 src/core/refetchSources/onlineSource.ts。事件 refetch 完全按需啟用構(gòu)造RefetchEventManager并傳入ApolloClient構(gòu)造函數(shù)即可激活事件監(jiān)聽(tīng)import { ApolloClient, InMemoryCache, RefetchEventManager, windowFocusSource, onlineSource, } from apollo/client; const client new ApolloClient({ link, cache: new InMemoryCache(), refetchEventManager: new RefetchEventManager({ sources: { // 窗口聚焦時(shí) refetch windowFocus: windowFocusSource, // 用戶(hù)恢復(fù)在線(xiàn)時(shí) refetch online: onlineSource, }, }), });默認(rèn)情況下所有活躍查詢(xún)都會(huì)在事件觸發(fā)時(shí) refetch查詢(xún)可逐事件關(guān)閉或整體關(guān)閉// 窗口聚焦時(shí)不 refetch但保留 online useQuery(QUERY, { refetchOn: { windowFocus: false }, }); // 關(guān)閉該查詢(xún)的所有事件驅(qū)動(dòng) refetch useQuery(OTHER_QUERY, { refetchOn: false, }); // 無(wú)條件啟用所有事件 useQuery(LIVE_DASHBOARD, { refetchOn: true, }); // 事件觸發(fā)時(shí)動(dòng)態(tài)決定是否 refetch useQuery(LIVE_DASHBOARD, { refetchOn: ({ source, payload }) { if (source windowFocus) { return someCondition(payload); } return true; }, });也可以按事件配置動(dòng)態(tài)回調(diào)useQuery(LIVE_DASHBOARD, { refetchOn: { windowFocus: ({ payload }) someCondition(payload), }, });per-query 按需啟用模式在defaultOptions.watchQuery.refetchOn設(shè)為false或true、回調(diào)函數(shù)再逐查詢(xún)開(kāi)啟。當(dāng)defaultOptions與 per-query 的refetchOn同時(shí)提供時(shí)兩者會(huì)合并——defaultOptions的值作用于 per-query 對(duì)象未顯式配置的事件const client new ApolloClient({ link, cache, refetchEventManager: new RefetchEventManager({ sources: { windowFocus: windowFocusSource }, }), defaultOptions: { watchQuery: { refetchOn: false }, }, }); // 只有該查詢(xún)會(huì)在窗口聚焦時(shí) refetch useQuery(DASHBOARD_QUERY, { refetchOn: { windowFocus: true } });自定義事件通過(guò) TypeScript 模塊增強(qiáng)注冊(cè)事件名與 payload 類(lèi)型再提供返回 Observable 的 source 函數(shù)發(fā)出值即事件 payloadimport { Observable } from apollo/client; import { filter } from rxjs; import { AppState, AppStateStatus, Platform } from react-native; declare module apollo/client { interface RefetchEvents { reactNativeAppStatus: AppStateStatus; } } const refetchEventManager new RefetchEventManager({ sources: { reactNativeAppStatus: () { return new Observable((observer) { const subscription AppState.addEventListener(change, (status) { observer.next(status); }); return () subscription.remove(); }).pipe( filter((status) Platform.OS ! web status active) ); }, }, });手動(dòng)觸發(fā)調(diào)用emit(eventName, payload)即可命令式觸發(fā)事件 refetchrefetchEventManager.emit(reactNativeAppStatus, active);無(wú)源事件Sourceless events某個(gè)事件沒(méi)有自動(dòng)檢測(cè)邏輯、只支持命令式emit時(shí)source 可聲明為true并將事件類(lèi)型聲明為void以省略 payload 參數(shù)declare module apollo/client { interface RefetchEvents { userTriggered: void; } } const refetchEventManager new RefetchEventManager({ sources: { userTriggered: true }, }); refetchEventManager.emit(userTriggered);注意對(duì)未注冊(cè) source 的事件調(diào)用emit會(huì)輸出警告并成為 no-op。自定義 handler事件觸發(fā)時(shí)默認(rèn) handler 調(diào)用client.refetchQueries({ include: active })再按各查詢(xún)的refetchOn設(shè)置過(guò)濾??舍槍?duì)某事件覆蓋 handler例如把所有查詢(xún)含standby都納入 refetchconst refetchEventManager new RefetchEventManager({ // ... handlers: { userTriggered: ({ client, source, payload, matchesRefetchOn }) { return client.refetchQueries({ include: all, onQueryUpdated: (observableQuery) { return matchesRefetchOn(observableQuery); }, }); }, }, });handler 必須返回RefetchQueriesResult或void返回void表示該事件跳過(guò) refetch。此外 4.2.0 還支持通過(guò)構(gòu)造選項(xiàng)defaultHandler或?qū)嵗椒╯etDefaultEventHandler覆蓋默認(rèn)handler未配置 per-source handler 時(shí)兜底運(yùn)行見(jiàn) src/core/RefetchEventManager.ts 中Options.defaultHandler的注釋說(shuō)明。4.5 4.2.x 補(bǔ)丁版本要點(diǎn)4.2.12修復(fù)多字節(jié) UTF-8 字符被 multipart 響應(yīng)塊切分后丟失的問(wèn)題PR #134004.2.11新增開(kāi)發(fā)模式警告——網(wǎng)絡(luò)結(jié)果寫(xiě)入緩存后回讀得到部分結(jié)果時(shí)提示通常指向merge/read函數(shù)未修復(fù)緩存缺失字段4.2.10修復(fù)optimisticResponse導(dǎo)致client.mutate返回類(lèi)型意外放寬、常量類(lèi)型變量導(dǎo)致returnPartialData/errorPolicy類(lèi)型被放寬、modern 簽名下未知選項(xiàng)未被 TypeScript 攔截等問(wèn)題refetch/fetchMore/useLazyQuery的execute返回類(lèi)型隨errorPolicy收窄4.2.9修復(fù)變量顯式傳undefined時(shí)默認(rèn)值未在緩存讀取中生效、export查詢(xún)對(duì)導(dǎo)出變量鍵控字段的緩存更新無(wú)響應(yīng)的問(wèn)題4.2.8connectToDevtools的setTimeout不再在非 Chrome/Firefox 環(huán)境觸發(fā)消除測(cè)試抖動(dòng)4.2.6緩存寫(xiě)入提速——僅在結(jié)果攜帶 stream 信息時(shí)才做stream檢測(cè)避免對(duì)每個(gè)寫(xiě)入字段做完整 ASTvisit嵌套字段上的stream不再被視為流式字段本身4.2.5從公共入口導(dǎo)出KeyArgsFunction與RelayFieldPolicy類(lèi)型4.2.4修復(fù)client.readFragment/client.readQuery忽略 options 對(duì)象中optimistic選項(xiàng)的問(wèn)題4.2.3graphqlv17 被接納為合法 peer dependency倉(cāng)庫(kù) patches 目錄中亦包含graphql-17-alpha9的補(bǔ)丁佐證4.2.2refetch 時(shí)若掩碼masked數(shù)據(jù)與上一結(jié)果深度相等則保持引用相等4.2.1修復(fù)useLazyQuery在渲染間隔中修改pollInterval不生效的問(wèn)題。五、3.x 至 2.x歷史演進(jìn)一瞥4.0 之前的歷史版本同樣記錄了大量關(guān)鍵演進(jìn)閱讀時(shí)可按需回溯3.14作為 4.0 前的過(guò)渡版本集中輸出廢棄警告是官方升級(jí)路徑的第 1 步3.8引入useFragment、useSuspenseFragment、useBackgroundQuery等 hooks 與新 SSR 能力3.6–3.7緩存、fetchMore、網(wǎng)絡(luò)狀態(tài)與 Link 鏈路的持續(xù)修復(fù)3.0InMemoryCache歸一化緩存與字段策略field policies成為主流2.x記錄了ObservableQueryTData, TVariables泛型化、QueryOptions與WatchQueryOptions分離、fetch policy 與 SSR 修復(fù)等歷史沿革。六、結(jié)語(yǔ)如何利用這份 CHANGELOG 指導(dǎo)開(kāi)發(fā)升級(jí)前先讀 4.0.0 Release Notes 的 Breaking Changes 清單走完3.14 → 裝 rxjs → codemod → 改初始化 → 改錯(cuò)誤處理 → 回歸測(cè)試的標(biāo)準(zhǔn)路徑接入 4.2 新特性事件驅(qū)動(dòng) Refetch 從 src/core/RefetchEventManager.ts 與 src/core/refetchSources 出發(fā)即可快速上手類(lèi)型安全能力則對(duì)照 src/core/types.ts 與DeclareDefaultOptions的模塊增強(qiáng)模式排查存量問(wèn)題按版本號(hào)在 CHANGELOG.md 中檢索對(duì)應(yīng)修復(fù)項(xiàng)通常能快速定位到源碼與測(cè)試如 src/core/tests做到改了什么、為什么改有據(jù)可查。從 4.0 的架構(gòu)重構(gòu)到 4.2 的類(lèi)型系統(tǒng)現(xiàn)代化與事件驅(qū)動(dòng) refetchApollo Client 的演進(jìn)主線(xiàn)始終圍繞更小的包、更準(zhǔn)的類(lèi)型、更靈活的框架適配展開(kāi)——這份 CHANGELOG 既是升級(jí)手冊(cè)也是理解客戶(hù)端緩存與狀態(tài)管理的絕佳源碼級(jí)教材?!久赓M(fèi)下載鏈接】apollo-clientThe industry-leading GraphQL client for TypeScript, JavaScript, React, Vue, Angular, and more. Apollo Client delivers powerful caching, intuitive APIs, and comprehensive developer tools to accelerate your app development.項(xiàng)目地址: https://gitcode.com/gh_mirrors/ap/apollo-client創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考