在移动应用和 Web 应用的开发中,前端状态管理和网络数据请求常常涉及到缓存问题。GraphQL 是一种出色的数据查询语言(query language),不仅能提高网络请求效率,还能减少不必要的数据传输。与此同时,GraphQL 还提供了缓存技巧来优化数据的处理和存储,缓存对应用性能优化至关重要。
本篇文章将探讨 GraphQL 中的缓存技巧,并提供详尽的解释和示例代码。
GraphQL 中的缓存概念
在 GraphQL 中,缓存是指在服务端操作返回的数据,以减少数据请求和传输。GraphQL 认为,数据缓存至服务端是一种更安全和更可控的方案。GraphQL 还引入了查询和类型等相关概念,以便更好地管理缓存技术。
GraphQL 中的缓存技术包括三个部分:
- 查询缓存:缓存查询结果以防止常见查询的冗余请求。
- 数据缓存:缓存解决数据依赖的过程,减少相应数据的查询操作。
- 类型缓存:缓存 GraphQL 类型或关联类型以避免未来查询中的类型错误。
查询缓存
GraphQL 中的查询缓存利用唯一的查询标识符存储查询结果。查询标识符包括查询名称和其中的参数。当查询相同时,GraphQL 会返回之前存储的查询结果,而不必重新查询。以下是利用 Apollo GraphQL 服务器实现查询缓存的示例代码:
-- -------------------- ---- ------- ----- - ------------ - - ------------------------- ----- - ---------------- - - ---------------------------------------- ----- - -------------------- - - ------------------------------ ----- - ------- - - ------------------- ----- - -------------------- - - --------------------------------- ----- -------- - - ---- ----- - ----------- -------- ------ - -- ----- --------- - - ------ - ------ --------- - ---- -- -- - ------ ------- ------ -- ----------- - - -- ----- ---------------- - ---------------------- --------- --------- --- ----- --------------- - ---------------------- --------- --------- --- ----- ------ - --- -------------- ------- ---------------- ----------------- - ------ --- ------------------- ---- -- - -- -- ------------- - -------------- -- - --- --------------------- ----- ------------------------- ----- - --- ----- ----- - - ----- ------------ ------- - ----------- ------ - -- ------------------------ ------ --- --- - ----- --------- -- ------------ -- - -------------------- ---
在上面的示例中,查询结果 Hello, GraphQL!
被缓存,下次查询相同时,将立即返回之前缓存的结果。
数据缓存
GraphQL 中的数据缓存是基于依赖项的缓存。每当有数据发生变化时,GraphQL 会缓存数据,并在必要时刻更新缓存。以下是利用 Dataloader 实现数据缓存的示例代码:
-- -------------------- ---- ------- ----- - ------------ - - ------------------------- ----- - ---------------- - - ---------------------------------------- ----- - -------------------- - - ------------------------------ ----- - ------- - - ------------------- ----- - -------------------- - - --------------------------------- ----- ---------- - ---------------------- ----- -------- - - ---- ---- - --- --- ----- ------- - ---- ----- - -------- ----- ---- - -- ----- ----- - - - --- ---- ----- ------- -- - --- ---- ----- ----- - -- ----- --------- - - ------ - ----- ----- --------- - -- -- - ----------- -- -- - ----- ------ - ------------------------ ------ ------------------- - -- ----- - ------------------- ----- -- -- -- - ----------- -- -- - ----- ------ - ------------------------ ------ ------------------- - - -- ----- ------ - ---------------------- --------- --------- --- ----- --------------- - ---------------------- --------- --------- --- ----- ---------------- - ---------- -- --------- ----- -- - ------------------------------------------- --- ------------------------ ------ ------- -- ----- ------ - --- -------------- ------- ---------------- ----------------- - ------ --- ------------------- ---- -- - -- -- ------------- - -------------- -- - --- --------------------- ----- ------------------------- ----- -- -------- -- --- -- -- -- ------------ --- ------ -------- -------- -- --- -------- - - ---------------- ----- -- ------- -- -- - -- ---------------------- --- ------- - ----- ------ - -- --- -- -- - ----- ---- - ------------ -- ---- --- ----- ------ ---- -- ----- -- -------------------------------------------------- --- ------ - ------ - -------- -- -- ---------------------------------------- -- - ---- - - - - --- ----- ----- - - ----- --------- ---- - -------- ---- - -- ---- - - -- ------------------------ ------ --- --- - --- --- -- ------------ -- - -------------------- ---
在上面的示例中,利用 Dataloader 实现单个数据的缓存。当查询 User
的字段 user
时,在数据缓存中使用类似于 find
的方式来查询 id,如果 id 存在,并返回它。如果数据不存在,则返回 null。需要注意的是,因为 Dataloader 利用可编辑 map 将相同的 key 组合成单个批处理请求,所以查询是至少的,无需做额外的处理。
类型缓存
GraphQL 中的类型缓存是一种基于带有相同请求服务的客户端应用程序的状态进行缓存的机制。例如,如果应用程序需要一个员工类型的数据结构来查询并在应用程序中缓存这个类型,那么这就是 typeCache 所做的工作。
以下是利用 GraphQL-tools 实现类型缓存的示例代码:
-- -------------------- ---- ------- ----- - ------------ - - ------------------------- ----- - ---------------- - - ---------------------------------------- ----- - -------------------- - - ------------------------------ ----- - ------- - - ------------------- ----- - -------------------- - - --------------------------------- ----- -------- - - ---- -------- - --- --- ----- ------- - ---- ----- - ------------ ----- -------- - -- ----- --------- - - ------ - --------- --------- - -- -- - ----------- -- -- - ------ -------------------------------------------- - -- --------- - ------------------- -- -- -- - ----------- -- -- - ------ -------------------------------------------- - - -- ----- ------ - ---------------------- --------- --------- --- ----- --------------- - ---------------------- --------- --------- --- ----- ------ - --- -------------- ------- ---------------- ----------------- - ------ --- ------------------- ---- -- - -- -- ------------- - -------------- -- - --- --------------------- ----- ------------------------- ----- -- ------------ -- -- -- ------------ --- ------------- --- -------- - - ---------------- -- ------- -- -- - ----------- - --- -------------- - - - --- ----- ----------- - ------------- - ---------- - --- -------------- - - - --- ---- ----- ------- -- - --- ---- ----- ----- - -- - ------------------- - ----- -------------- - --------------- -- ---------------- - ------ --------------- - ----- -------- - --------------------- -- ---- --- ---- -- ---------- - -------------- - --------- ------ --------- - ------ ----- - - ----- ----- - - ----- ------------- ---- - ------------ ---- - -- ---- - - -- ------------------------ ------ --- --- - --- --- -- ------------ -- - -------------------- ---
在上面的示例中,用 EmployeeAPI 类型实现了基本的缓存。EmployeeAPI 类型中包含了一些基本的缓存方法,这些方法可以帮助应用程序更好地实现数据的存储和提取。最终缓存类型被设为一个对象,其中每个属性都是一个存在于缓存存储器中的所需类型。此示例中缓存了单独的 Employee 类型,但同时也可缓存具有相同属性的多个类型。
结论
GraphQL 中的缓存技术包括查询、数据和类型缓存。查询缓存、数据缓存和类型缓存各自具有优点和局限性,应对缓存方案的选择需要结合具体业务场景进行权衡。
在开发过程中,GraphQL 缓存技术可以大大提高服务端的性能,减少不必要的资源浪费和网络传输。掌握 GraphQL 缓存技术可以帮助前端开发者更轻松地实现性能优化的目标,同时也能够增强应用程序的可扩展性和稳定性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/670921a3d91dce0dc876b6e2