前端线上问题如何调试

本文记录了在Vue项目中遇到的一个线上环境特有的错误:`Uncaught TypeError: Cannot read properties of undefined(reading 'refs')`。通过分析错误信息、利用打包工具、本地模拟线上环境、搜索引擎辅助以及源码调试,最终定位到问题原因并提出解决方案。强调了在开发过程中注意警告信息和熟悉调试技巧的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录Vue开发过程中遇到的问题,测试环境以及本地显示都没有问题,但是一上线就出现问题,于是对于这个问题进行排查,在此记录排查问题的步骤以及方法,希望对大家有帮助。

错误信息:Uncaught TypeError: Cannot read properties of undefined(reading ‘refs’)

更新:我觉得devlopment环境下报警告而production环境之间报错的处理不够友好

于是我给Vue提了一个issue,希望能做些优化,具体的问题读完全文后不懂的话可以去看这个issue

image.png

此项目是基于naive-ui+vite进行开发的

线上报错信息以及显示如下:
请添加图片描述

测试环境和本地显示如下:
请添加图片描述
如何查找问题?

  1. 先确定问题出在哪里,尽管这是线上环境,但是我们依旧可以从报错信息里找到对应的错误文件。

    • 打开错误的更多信息进行文件查看,这里一看全是打包后的文件,根本不知道是哪个文件。
      请添加图片描述

    • 所以我们可以利用sourcemap来重新打包,附上vite的配置

    export default defineConfig({
      plugins: [vue(), vueJsx()],
      build: {
        // 开启sourcemap
        sourcemap: true,
      },
    })
    
    • 利用http-server进行本地打包,然后在浏览器上查看打包的问题,因为是线上问题,所以利用库打包并进行 debug。

    请添加图片描述

    这里我们看到了错误的相关文件,只需要顺着相关文件去查找问题就行。

  2. 先利用现有的信息去谷歌搜索,因为很多时候这样的问题已经有人遇到过了,所以检索获取结果是最快的问题解决方案
    请添加图片描述

通过谷歌搜索我们可以看出有很多条问题,那些相关的问题都可以点击去看看,是否有符合你的解决方案。(比较好的答案有GitHubissuestackoverflow以及掘金上的答案)

我直接点进去上图中框选的那条信息
请添加图片描述
根据问题结果去反查错误的相关文件,如果是相关问题就直接解决,推荐大家多用 vscode 的全局搜索比较方便文件内的话多用 ctrl+f搜索

  1. 如果网上的答案都不能解决你的问题,那么就需要开始自己debug

    • 首先我根据错误点进去查看,看看是什么引发的错误
      请添加图片描述

      发现是在owner context上取 refs 时无法取到,也就是说 ownerundefined

      在往上看,发现这是个production上会报的错误,但是其实本地也会报,于是可以转为本地debug

      当然本地无法调试的情况,那么就根据文件报错的地方进行debugger,然后重新打包调试。

  2. 在本地服务上进行调试

请添加图片描述

可以看到确实有警告信息了,通过源码就知道了为啥只有production上会有问题了,而其他环境则不会有问题。

当然这也侧面印证了我们在开发过程中也需要多多注意警告⚠️

发现在Test文件,上面都是一些naive-ui的组件,并且还是某一条row造成的,于是去查看对应的row的数据以及columns数据的构造。

通过debugger发现构造的cell数据的reffalse
请添加图片描述

继续往下进行 debugger, 发现走入到setRef里面了,并且把reffalse传入了。
请添加图片描述
请添加图片描述

到了这里就发现问题了,就是因为这个 cellref被编译成了false了。

  1. 发现问题后开始解决问题,如果有简单的编译原理知识是更好的,没有也不重要,只要顺着调试线继续走下去就能解开一团乱线。

    从上面我门知道patch的是两个vnode类型也是很重要的,它让你不需要有那么多的背景知识可以快速解),那么我们就需要从vnode下手。

    找到生成vnoderef的地方。

    // vnode.ts
    function createBaseVNode(
    	type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
      props: (Data & VNodeProps) | null = null,
      children: unknown = null,
      patchFlag = 0,
      dynamicProps: string[] | null = null,
      shapeFlag = type === Fragment ? 0 : ShapeFlags.ELEMENT,
      isBlockNode = false,
      needFullChildrenNormalization = false
    ) {
        const vnode = {
          __v_isVNode: true,
          __v_skip: true,
          type,
          props,
          key: props && normalizeKey(props),
          // ref为false是因为props传入了false。。。
          ref: props && normalizeRef(props),
          scopeId: currentScopeId,
          slotScopeIds: null,
          children,
          component: null,
          suspense: null,
          ssContent: null,
          ssFallback: null,
          dirs: null,
          transition: null,
          el: null,
          anchor: null,
          target: null,
          targetAnchor: null,
          staticCount: 0,
          shapeFlag,
          patchFlag,
          dynamicProps,
          dynamicChildren: null,
          appContext: null,
          ctx: currentRenderingInstance
        } as VNode
        // ...
      }
    

    于是回到Test的代码里面检查

    const columns = [
      // ....
      {
        title: 'Address',
        key: 'address',
        width: 100,
        ellipsis: {
          tooltip: true
        }
      },
      {
        title: 'Another Address',
        key: 'anotherAddress',
        width: 100,
        render(row) {
          // 当age大于40是会传入false,于是就G了
          const ellipsisProps = row.age < 40 && { tooltip: true } 
          // debugger;
          return h(NEllipsis, ellipsisProps, () => row.anotherAddress)
        }
      }
    ]
    

总结

通过这次debugger,确实有一些问题值得总结

  1. 写代码还是要细心啊,如果可能多补补脑子,少犯一些低级错误。
  2. 调试真的不难,开启sourcemap打上debugger,一步一步调试,总能找到解决的线头。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值