前端开发问题排查指南
遇到问题了?也许这个能帮到你 ¯\_(ツ)_/¯。
问题排查
本指南未包含您遇到的问题
如果您遇到的前端开发问题不在本指南中,请考虑更新本指南,添加您遇到的问题和可能的解决方案。这样,未来的开发者就能带着您的经验和知识,更成功地面对这些挑战。
测试问题
出现 Property or method 'nodeType' is not defined 错误,但您并未使用 nodeType
这个问题可能发生在 Vue 组件测试中,当某个断言失败时,Jest 尝试在控制台中打印差异时会抛出错误。有记录表明,使用 toEqual 且属性为数组也可能是导致此问题的因素。
请观看此视频获取深入的分析和调查。
解决方案 - 尝试克隆带有 Vue 监听器的对象
- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
+ expect(cloneDeep(wrapper.findComponent(ChildComponent).props())).toEqual(...)
解决方案 - 尝试使用 toMatchObject 替代 toEqual
- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
+ expect(wrapper.findComponent(ChildComponent).props()).toMatchObject(...);
toMatchObject 实际上改变了断言的性质,如果期望值中缺少某些项,它不会失败。
脚本问题
在 GitLab 仓库中运行脚本时出现 core-js 错误
以下命令假设您已在 ~/workspace/gdk 目录中设置了 GitLab 仓库。在 GitLab 仓库中运行脚本(如代码转换)时,可能会遇到类似这样的 core-js 问题:
~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:7
$({
^
TypeError: $ is not a function
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:6:1)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Module._compile (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Object.newLoader [as .js] (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/esnext.global-this.js:2:1)解决方案 - 尝试将脚本移至单独的仓库,并指向 GitLab 仓库中的文件
使用 Vue 组件问题
渲染使用 GlFilteredSearch 的组件,且该组件或其父组件使用 Vue Apollo
在尝试渲染我们的 GlFilteredSearch 组件时,您可能会在组件的 provide 函数中收到错误:
cannot read suggestionsListClass of undefined
目前,vue-apollo 尝试在组件生命周期的 beforeCreate 部分手动调用组件的 provide()。这意味着当 provide() 引用了 props(这些 props 实际上是在 created 之后才设置)时,就会出错。
有关更多上下文,请参阅此已关闭的 MR。
解决方案 - 尝试将 apolloProvider 提供给顶级 Vue 实例选项
如果 VueApollo 看到在 $options 中提供了 apolloProvider,它将跳过手动运行 provide()。
new Vue(
el,
+ apolloProvider: {},
render(h) {
return h(App);
},
);
Apollo Client 问题排查
写入缓存时出现控制台错误
如果您看到类似 Missing field 'descriptionHtml' while writing result 的错误,这意味着我们在向 Apollo 客户端缓存写入时没有遵循 GraphQL 响应结构。您似乎在 Web 应用程序中遇到了 GraphQL 错误(“Missing field ‘description’"),这可能与您处理 Apollo Client 缓存和数据更新的方式有关。错误堆栈跟踪提供了问题发生的 Apollo Client 代码特定部分的线索。
核心问题:
错误 “Missing field ‘description’” 表明您的 GraphQL 查询期望响应中有一个名为 “description” 的字段,但您从后端收到的数据(或 Apollo Client 处理的数据)缺少该字段。这导致 Apollo Client 尝试用不完整的数据更新存储时失败。
要调试此问题,请按照以下步骤操作:
- 打开错误堆栈的开发者控制台
Missing field 'description' while writing result {
"type": "DESCRIPTION",
"lastEditedAt": null,
"lastEditedBy": null,
"taskCompletionStatus": null,
"__typename": "WorkItemWidgetDescription"
}- 仔细检查您的 GraphQL 查询,确保它请求了 “description” 字段。如果未包含,Apollo Client 将无法在响应中找到它。
- 后端可能没有在 “WorkItemWidgetDescription” 类型的响应中返回 “description” 字段。验证您的后端 API 是否按预期正确发送数据。
- 使用
cache.readQuery方法检查 Apollo Client 缓存的内容。验证相关查询的缓存数据中是否存在 “description” 字段。 - 打开错误堆栈跟踪,表明问题可能与 Apollo Client 如何向其缓存写入数据有关。缓存可能未正确更新,导致缺少字段。
- 在您的 Apollo Client 代码中添加控制台日志(例如,在写入缓存之前和之后),以跟踪正在处理的数据并识别 “description” 字段可能缺失的位置。
解决方案
确保您在 Apollo Client 代码中使用正确的 writeQuery 或 writeFragment 方法来更新缓存,包含完整的数据,包括 “description” 字段。
您应该能够在堆栈跟踪中看到此问题的来源方法。确保在写入缓存时添加 “description” 字段。
使用相同变量的查询未被缓存
Apollo GraphQL 查询在以下几种情况下可能不会被缓存:
-
缓存未命中、部分缓存、查询失效或变更: 如果查询只返回部分数据,或者存在缓存未命中(当请求的部分数据不在缓存中时),Apollo 可能无法有效缓存结果。
如果与查询相关的数据已被失效或更新,缓存可能没有有效信息。例如:
使用变更(mutations)时,除非您配置了
refetchQueries或在变更后手动更新缓存,否则缓存可能不会自动更新。例如:在第一个查询中,您有一些字段在后续查询中未被请求
query workItemTreeQuery($id: WorkItemID!, $pageSize: Int = 100, $endCursor: String) {
workItem(id: $id) {
namespace {
id
}
userPermissions {
deleteWorkItem
updateWorkItem
}
}
}query workItemTreeQuery($id: WorkItemID!, $pageSize: Int = 100, $endCursor: String) {
workItem(id: $id) {
namespace {
id
+ fullPath
}
userPermissions {
deleteWorkItem
updateWorkItem
+ adminParentLink
+ setWorkItemMetadata
+ createNote
+ adminWorkItemLink
}
}
}
-
fetchPolicy设置: Apollo Client 使用 fetchPolicy 来控制查询如何与缓存交互。根据策略的不同,如果 fetchPolicy 设置为no-cache,查询可能会完全绕过缓存。此策略确保查询的任何部分都不会写入缓存。每个查询直接从服务器获取数据,不将任何结果存储在缓存中,因此会多次获取查询。 -
当从不同的 Apollo Client 实例触发相同的查询时。可能是触发这两个查询的客户端来自不同的客户端实例。
-
缺少
id或__typename: Apollo Client 使用id和__typename来唯一标识实体并缓存它们。如果这些字段在您的查询响应中缺失,Apollo 可能无法正确缓存结果。 -
复杂或嵌套查询: 某些查询可能过于复杂或涉及嵌套查询,Apollo Client 可能难以正确缓存。如果返回的数据结构不能很好地映射到缓存架构,可能会发生这种情况,需要手动缓存管理。
-
分页查询: 对于涉及分页的查询(如使用 fetchMore 的查询),除非显式更新缓存,否则 Apollo 可能无法正确缓存结果。
在所有这些情况下,您可能需要配置 Apollo 的缓存策略或手动更新缓存,以有效处理查询缓存。