ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

@urql/svelte 版本演进全解析:从 operationStore 到函数式 Store API

@urql/svelte 版本演进全解析:从 operationStore 到函数式 Store API 前端【免费下载链接】urqlThe highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.项目地址https://gitcode.com/gh_mirrors/ur/urql点击查看免费下载urql/svelte是 urql 生态中为 Svelte 框架提供的官方绑定包它把 GraphQL 查询、变更与订阅封装为符合 Svelte 响应式模型的原生 Store。本文以该包在仓库中的完整变更日志packages/svelte-urql/CHANGELOG.md为主线梳理其从 0.1.0-alpha 到 5.0.0 的演进脉络逐一解读每个版本背后的重大架构决策、破坏性变更与修复细节并结合 packages/svelte-urql/src 下的当前源码讲清queryStore、mutationStore、subscriptionStore与Pausable等核心 API 的底层实现。读完本文你将掌握该包版本升级时的行为差异、当前函数式 Store API 的完整用法以及如何利用上下文 API 在 Svelte 组件中共享 Client。一、包的定位与版本节奏urql/svelte的包描述是 A highly customizable and versatile GraphQL client for Svelte它本身并不包含 GraphQL 请求的核心逻辑而是依赖urql/core提供的基础Client、exchange 架构与结果类型。从当前 packages/svelte-urql/package.json 可以看到当前版本为5.0.0对应urql/core6.0.0peerDependencies声明urql/core: ^6.0.0与svelte: ^3.0.0 || ^4.0.0 || ^5.0.0即同时兼容 Svelte 3、4、5运行依赖仅两个urql/core与wonka^6.3.2wonka 是 urql 内部使用的响应式流库。从变更日志可以清晰看到一条演进主线早期0.x是 API 探索期 → 1.x 是 operationStore 稳定期 → 2.0.0 发生了函数式 Store架构重写 → 3.x 走向 TypeScript 严格化 → 4.x 引入流式结果语义并最终适配 Svelte 5 → 5.0.0 跟随 core 6.0 大版本。下面按阶段逐层展开。二、早期 0.xAPI 探索与形态试验0.1.0-alpha.0 与 0.1.x起步与构建兼容初始版本0.1.0-alpha.0为首个 Alpha 发布。随后 0.1.x 阶段主要解决工程与依赖问题0.1.0将urql/core依赖的 minor 版本提升到^1.10.10.1.1修复 Node.js v13experimental-modules与 v14 下的模块支持确保.mjs文件能被 Webpack 等打包器正确解析0.1.2修复 Webpack 环境下.mjs导入时错误解析package.json:main而非module的问题0.1.3将graphql的 peer dependency 范围扩展到^15.0.0并强制提升urql/core版本以修复cache-and-network策略的底层缺陷。这一阶段urql/svelte的 API 形态尚未定型变更以让包在各种 Node/打包器环境下跑起来为主。0.2.xmutation API 走向统一0.2.0将mutate()的 API 从多个分离参数改为接收一个 options 参数提升与其他 API 的一致性0.2.1提升urql/core确保 exchange 具备dispatchDebug此前可能导致崩溃0.2.2mutate直接返回 Promise而非惰性的 Promise-like 对象0.2.3在package.json的exports字段中补充./package.json入口以兼容rollup-plugin-svelte等工具0.2.4将 wonka 最低版本提升到^4.0.14规避 React Native 使用 uglify-es 压缩构建时可能产出的损坏 bundle。0.3.0三种使用形态正式确立0.3.0是一次关键的 API 设计收敛它把操作重构为支持多种 Svelte 使用模式变更日志给出了完整的形态示例// 标准用法立即执行 mutate({ query, variables })() // Subscribable 用法模板中响应式读取 $: result mutate({ query, variables }); // 柯里化用法先创建执行函数后触发 const executeMutation mutate({ query, variables }); const onClick () executeMutation(); // 柯里化 运行时覆盖 variables const executeMutation mutate({ query }); const onClick () await executeMutation({ variables }); // 响应式查询每次 variables 变化都重新执行 $: result query({ query: TestQuery, variables }); // 跨时间保持状态的响应式用法 const testQuery query({ query: TestQuery }); // - 即使 variables 变化状态也得以保留 $: result testQuery({ variables }); // 基于 Promise 的回调用法 const testQuery query({ query: TestQuery }); const doQuery async () await testQuery; // - doQuery 的调用还会同步更新订阅中的 result $: result query({ query: TestQuery, variables });这四种形态标准调用、可订阅、柯里化、Promise 化奠定了urql/svelte的核心设计哲学API 返回的不仅仅是一个结果而是一个既可作为 Store 订阅、也可作为函数调用的可复用操作句柄。0.4.0结果中暴露 operation0.4.0为查询、变更和订阅的结果统一追加了operation字段使 UI 层可以直接从结果中读到本次操作的完整请求信息query、variables、context 等。这一点在当前源码中依然保留OperationResultState扩展自OperationResult并始终携带operation字段见 packages/svelte-urql/src/common.ts 中的initialResult。三、1.xoperationStore 稳定期与 Svelte 能力补齐1.0.0API 宣告稳定1.0.0是urql/svelte正式稳定版本。变更日志明确写道新 API 由query、mutation、subscription三个工具函数构成它们在组件生命周期内被调用并接收operationStore一种同时封装GraphQL 操作输入与结果输出的 writable store。从 1.0.0 起包的 API 契约基本冻结后续 1.x 的变更都是在此骨架上的能力补全。1.1.xpause 与 stale 语义1.1.0新增pause选项用于停止查询或订阅的自动执行1.1.1修复查询结果缺失stale标志更新的问题1.1.2将OperationStore中的void联合类型替换为undefined便于 TypeScript 下的空值属性访问1.1.3为所有直接或间接接收DocumentNode的方法接入TypedDocumentNode类型推断使OperationResult与Operation的类型可以从文档节点自动推导1.1.4跟随urql/core内置的gql标签函数——它在解析文档时会仅警告局部重复的 fragment 名称并为 key 缓存预填解析后的DocumentNode。1.2.xOperation 模型演进1.2.0移除已废弃的operationName属性改用Operation.kindquery | mutation | subscription并引入makeOperation工具1.2.1允许mutation接收更宽松的GraphQLRequest部分对象可不带key或variables1.2.2构建流程移除 closure-compiler1.2.3放宽OperationStore与subscription的类型允许data结果类型与原始Data类型不同可从TypedDocumentNode提取同时改用client.executeMutation而非client.mutation。1.3.xreexecute 与更细粒度的更新1.3.0提升operationStore在query、variables、context变化时的更新粒度并新增operationStore(...).reexecute()方法——它可选地接收一个新的 context 值并强制刷新 store从而让查询可以重新执行1.3.1为operationStore的返回值补充缺失的pause方法1.3.2修复operationStore初始化时fetching: false的语义——只有当查询或其他操作真正开始执行时才置为true1.3.3将graphql的 peer 依赖范围扩展到^16.0.0并建议升级后使用npm dedupe或npx yarn-deduplicate消除重复依赖。值得注意的是reexecute这一能力在后来的 2.0.0 重写中一度被移除又于 4.1.0 重新恢复详情见后文。四、2.0.0函数式 Store API 的架构重写2.0.0是urql/svelte历史上最重要的一次破坏性变更。变更日志对此有非常坦诚的说明我们收到了大量来自 Svelte 社区的反馈与 issue。此前的绑定倾向于使用一个Store 单例来读写状态外加一个独立的信号来启动操作。但 Svelte 通常要求更多的灵活性因此我们把 API 重新改回纯函数式 API——它只负责创建 Store这与最初版本的设计更接近。这次重写意味着放弃 operationStore 单例模式改为每次调用queryStore/mutationStore/subscriptionStore返回独立的响应式 Store引入 wonka 作为内部流处理底座wonka 在此后一直是运行依赖同阶段的2.0.1修复了 Node.js ESM 下urql/core的 re-export 检测问题涉及cjs-module-lexer否则会引发运行时错误2.0.2则修复了subscriptionStore与queryStore因derived导致订阅被提前终止的问题并让所有操作的 variables 变为可选。从当前 packages/svelte-urql/src/queryStore.ts 的实现可以看到这次重写的最终形态queryStore内部先用createRequest创建请求、用client.createRequestOperation构造query操作再通过writable wonka 的switchMap/concat/scan组合把Client的结果流映射进 Svelte store最后用derived包装并混入createPausable的pause/resume/isPaused$能力。这正是纯函数式、只负责创建 Store的架构。五、3.xTypeScript 严格化与 Wonka 63.0.0带来三组重大变更告别 IE11移除 IE11 支持产物不再保证 ES5 兼容更严格的 variables 类型当泛型被设置或推断时要求 variables 必须始终传入且匹配 TypeScript 类型——这是一项对 TS 用户的潜在破坏性变更升级 Wonka v6wonka^6.0.0本身无破坏性变更但产物目标调整为 ES2015且库本身已全面迁移到 TypeScript便于社区贡献。后续 3.0.x 均为类型修补3.0.1调整泛型仅含可空键时的 variables 类型推导3.0.2把剩余的Variables泛型默认值从object迁移到Variables extends AnyVariables AnyVariables此前遗漏的部分会导致与AnyVariables不兼容3.0.3修复 TS/Rollup 构建时类型生成路径被解析到src而非types目录的问题3.0.4修复类型工具——当TypedDocumentNode没有Variables或全部为可选时不应把variables属性变更为可选避免破坏代码生成器等包装场景。六、4.x流式结果、订阅语义修正与 Svelte 54.0.0hasNext / stale 必填与 handler 归位4.0.0是继 2.0.0 之后又一次重要的破坏性大版本OperationResult.hasNext与OperationResult.stale变为必填字段。如果自定义 exchange 直接构造结果必须补上这两个字段或改用makeResult、mergeResultPatch、makeErrorResult等辅助函数handler用于聚合订阅事件的函数从mutationStore移到subscriptionStore。日志明确指出它此前被意外定义并实现到了错误的 store 上本应属于subscriptionStore——这解释了为什么当前subscriptionStore的第二个参数是SubscriptionHandler而mutationStore没有该参数允许 mutation 在hasNext: true时持续更新绑定结果以支持 deferred 与 streamed 结果对应 GraphQL 的defer/stream指令场景。同时4.0.0 还升级了 wonka 至^6.3.0、修复发布包的 source map补充sourcesContent、修正路径并为所有 urql 绑定包补充了 TSDoc 注释。4.0.x发布链路与 Svelte 版本兼容4.0.1发布时启用 npm provenance供应链可溯源4.0.2修正构建流程以生成正确的 source map4.0.3扩展 peer dependency 范围以支持 Svelte^4.0.04.0.4修复queryStore与subscriptionStore在writable调用StartStopNotifier时未订阅的问题——此前这两个 store 一旦被取消订阅过就会失效无法重新建立对Client的订阅导致失去响应。4.1.x / 4.2.x能力回归与现代化4.1.0重新加回reexecute函数2.0.0 重写时被移除的能力并随urql/core4.3.0升级4.1.1随urql/core5.0.0升级4.2.0将urql/core同时标记为 peer dependency 与普通依赖并修复订阅 handler 不应接收到null值的问题4.2.1在peerDependencies中加入对 Svelte 5 的支持^5.0.04.2.2为查询与变更结果补充hasNext的类型定义4.2.3发布包时省略压缩文件与 source map 中的sourcesContent。5.0.0跟随 core 65.0.0主要是一次依赖对齐升级到urql/core6.0.0对应 PR #3789 与 #3807 的依赖更新。这也是当前仓库中urql/svelte的最新版本。七、当前 API 全貌从源码看函数式 Store 的实现结合 packages/svelte-urql/src/index.ts 的导出当前包对外提供四组能力queryStore、mutationStore、subscriptionStore、Context API同时 re-export 全部urql/core。queryStore可暂停、可重执行的查询 StorequeryStore的参数与返回类型在 packages/svelte-urql/src/queryStore.ts 中有完整的 TSDoc 定义参数类型说明clientClient执行查询所用的 Client通常取getContextClient()querystring \| DocumentNode要执行的查询可为纯字符串或 GraphQL 文档节点variables?object查询变量随 POST 请求体发送requestPolicy?RequestPolicy缓存策略默认cache-firstpause?boolean是否以暂停状态启动停止自动执行context?PartialOperationContext操作上下文如additionalTypenames、url等返回值为OperationResultStore Pausable { reexecute }。底层实现的关键链路是createRequest(args.query, args.variables)构造请求client.createRequestOperation(query, request, context)生成操作对象用writable包裹操作与暂停状态再以 wonka 的switchMap订阅client.executeRequestOperation(operation)的结果流每次结果到达时通过scan合并进状态fetching在请求发起时置true、结果到达后置false对应stale、hasNext等字段的语义reexecute(context)会合并新的 context、重置暂停状态并写入新的操作对象从而触发一次全新执行。对应地packages/svelte-urql/src/queryStore.test.ts 验证了创建即 Svelte storeoperation.kind 为 querypause/resume 切换 isPaused$等行为。mutationStore手动触发的变更 StoremutationStore与queryStore的最大区别是不会自动执行它同样创建请求与mutation操作见 packages/svelte-urql/src/mutationStore.ts但只在有订阅者时才执行一次且初始状态即fetching: true。典型用法是把mutationStore(...)放进一个事件回调中const updateTodo ({ id, title }) { result mutationStore({ client, query: gql mutation ($id: ID!, $title: String!) { updateTodo(id: $id, title: $title) { id title } } , variables: { id, title }, }); };需要注意的错误语义mutationStore返回的 Promise 永远不会 reject失败时同样 resolve只是result.error会被设置为CombinedError网络错误与 GraphQL 错误都会被包装进去。packages/svelte-urql/src/mutationStore.test.ts 同样验证了operation.kind mutation与文档打印结果。subscriptionStore聚合订阅事件subscriptionStorepackages/svelte-urql/src/subscriptionStore.ts与queryStore一样支持pause且额外接受第二个参数handler——这正是 4.0.0 从mutationStore移过来的SubscriptionHandlertype SubscriptionHandlerT, R (prev: R | undefined, data: T) R;handler 会在每次订阅事件到达时以上一次数据或undefined 新数据为入参把结果归约进result.data。典型场景是订阅单个通知事件、却要在界面上展示通知列表subscriptionStore( { query: NotificationsSubscription }, function combineNotifications(notifications [], data) { return [...notifications, data.newNotification]; } );从源码看scan阶段会优先调用 handler 聚合数据若未提供 handler 则直接透传最新数据。Pausable 与 OperationResultStorepackages/svelte-urql/src/common.ts 定义了本包的类型基础OperationResultStateOperationResultfetching标志OperationResultStoreReadableOperationResultStatePausable{ isPaused$: Writableboolean; pause(): void; resume(): void }initialResult{ operation, fetching, data, error, extensions, hasNext, stale }的初始值。queryStore与subscriptionStore的返回值都混入Pausable通过内部createPausable实现这意味着你可以在模板中通过$store.isPaused$读取暂停状态并随时调用store.pause()/store.resume()。Context API共享 Client 的标准姿势与 手动传入 client 的显式风格并存packages/svelte-urql/src/context.ts 提供了基于 Svelte Context API 的三个包装函数setContextClient(client)向子组件提供 Client内部调用setContextgetContextClient()从上下文取回 Client开发环境下找不到会抛出 Did you forget to call setContextClient? 错误initContextClient(options)new Client(options)setContextClient的便捷组合。仓库中的 examples/with-svelte/src/App.svelte 展示了标准启动流程用setContextClient(new Client({ url, exchanges: [cacheExchange, fetchExchange] }))提供 Clientexamples/with-svelte/src/PokemonList.svelte 则在子组件中通过getContextClient()配合$:响应式语句创建queryStore并使用reexecute({ requestPolicy: network-only })做强制刷新——分页、加载态与错误态一应俱全。八、Vite 集成与升级注意事项Vite 下的optimizeDeps配置由于urql/svelte在模块顶层使用了 Svelte 的 context/setContext 相关能力若以 Vite 作为打包器可能遇到Function called outside component initialization错误导致页面无法加载。官方文档docs/basics/svelte.md给出的解决办法是把urql/svelte加入依赖预构建排除列表{ optimizeDeps: { exclude: [urql/svelte], } // 其他配置 }仓库中的 examples/with-svelte/vite.config.mjs 可作为参考模板。跨大版本升级清单结合变更日志跨版本升级时值得重点核对的行为差异有2.0.0API 从 operationStore 单例切换为函数式 Store旧版operationStore/query({...})写法需迁移到queryStore/mutationStore/subscriptionStore3.0.0产物不再兼容 ES5IE11 淘汰Variables泛型默认值改为AnyVariables严格类型模式下 variables 必须匹配泛型4.0.0自定义 exchange 构造结果时hasNext与stale变为必填用makeResult/mergeResultPatch/makeErrorResulthandler从mutationStore移到subscriptionStorewonka 提升到^6.3.04.0.4若你的代码曾取消订阅后重新订阅 store请确保升级到包含该修复的版本5.0.0跟随urql/core6.0.0升级时建议npm dedupe或npx yarn-deduplicate以消除重复的urql/coreSvelte 版本当前 peer 范围为^3.0.0 || ^4.0.0 || ^5.0.0Svelte 3 起步即可用但若使用 Svelte 5 的 runes 等新语法请同时关注 store 订阅语义与组件初始化顺序的差异。九、结语一份变更日志背后的设计史回看 packages/svelte-urql/CHANGELOG.md 的 47 个版本记录能读到的不仅是依赖版本号更是urql/svelte的设计取舍史从早期 API 的反复试验0.x到 operationStore 的稳定与能力补全1.x再到纯函数式、只创建 Store的彻底重构2.0.0继而转向 TypeScript 严格化3.x与流式结果语义4.x最终对齐 core 6 大版本5.0.0。配合 packages/svelte-urql/src 的当前实现、packages/svelte-urql/src/queryStore.test.ts 与 packages/svelte-urql/src/mutationStore.test.ts 的测试用例、docs/basics/svelte.md 与 docs/api/svelte.md 的使用文档以及 examples/with-svelte 的完整示例你可以在当前仓库中获得从为什么这么设计到怎么用、怎么升级的完整闭环。赞分享前端【免费下载链接】urqlThe highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.项目地址https://gitcode.com/gh_mirrors/ur/urql点击查看免费下载相关推荐tanstack/svelte-form 版本演进全解析从 1.21 到 1.33 的 API 迭代、性能优化与 SSR 修复tanstack/svelte form 版本演进全解析从 1.21 到 1.33 的 API 迭代、性能优化与 SSR 修复 本文以 tanstack/前端UI组件Windows 快捷键冲突怎么排查OpenArk 一键定位全局热键归属Windows 快捷键冲突怎么排查OpenArk 一键定位全局热键归属 CtrlC 突然失灵、刚配好的快捷键被新装软件悄悄抢走——这种 Windows 热键网络安全逆向工程桌面应用in_app_purchase 3.x 版本演进与迁移指南从 App Store 到 Google Play 的统一内购 API 全解析in_app_purchase 3.x 版本演进与迁移指南从 App Store 到 Google Play 的统一内购 API 全解析 Flutter 官方跨平台移动开发UI组件开发工具上一篇从0构建类似any-rule的正则工具核心技术解析下一篇react-native-image-picker性能优化大赛开发者优化方案征集创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表