我是这样重构和优化组件的

Author

华丽

PublishDate

2024-03-14

category

编程

AI 总结

这篇文章介绍了一个名为 vue-hook-optimizer 的工具,这个工具可以帮助优化 Vue 和 React 组件代码,通过分析代码使用情况以及链式调用、代码逻辑耦合等方面给出优化建议。作者认为,这个工具能帮助开发者更好地梳理和优化代码,从而提高代码质量。

引言

有时我们不得不重构旧代码,可能一个文件里有成百上千行的代码,太复杂难以理解。

这种场景想必大家都遇到过,特别是在工作中接受了一个新的项目,并且需要在此之上开发新的功能。如果新的功能比较简单,或者新功能较为独立,那么在旧代码的基础上编写代码的难度还是比较低的。但是如果我们的需求,需要在理解旧业务、梳理旧代码,并在旧代码的基础上增加或者修改功能,那么我们就不得不对旧代码进行重构或优化。

另一个场景是说,我们在开发新功能时,全身心投入在功能的开发下,而暂时忽略了代码的可读性和可维护性,这是非常正常且合理的。但是我们最好不要直接将这样的代码作为我们的成果,这是非常不负责任的表现。

所以我想开发一个工具来帮助我们分析代码,并找出变量和方法之间的关联关系。我们可以发现一些变量是孤立的,一些方法是过度关联的,然后我们可以重构它们。今天的文章将会主要围绕 vue-hook-optimizer 来介绍一些我常用的优化代码的方式。注意,这里我们主要优化代码本身,针对性能的优化不在今天的讨论范围。如果大家感兴趣,我们后面可以再专门进行讨论。

优化方案

工具介绍

今天主要用到的工具 vue-hook-optimizer 是我开发的专门针对 vue 和 react 组件的代码优化辅助工具,它使用 babel 分析组件的源码并生成 ast 语法树,收集信息并展示一定的优化建议。同时 vscode 作为我们日常的开发工具,也提供了强大的优化和重构能力。

常见问题

优化无用代码

如果我们的代码冗长,并且经过了多次的修改和维护,那么代码中很大程度上会出现冗余的内容,比如说未使用的变量和函数。这是常见的例子。

<script setup lang="ts">
const notUsedVar = getData()
const usedVar = getData()
</script>
<template>
  <div> {{usedVar}} </div>
</template>

在上面的代码中,notUsedVar 变量其实是无效变量,因为它并没有在模板和其他方法中被使用。这个简单的示例是显而易见的。但是如果我们的代码非常冗长,代码的调用是复杂的,那么我们可能无法很快的找出未使用的变量或函数。

<script setup lang="ts">

function getData1() {
  return new Person()
}

function getData2() {
  return new Person()
}

const data1 = getData1()
const data2 = getData2()

const data3 = computed(() => data1.value)

</script>
<template>
  <div> {{data2}} </div>
</template>

在上面的代码中,模板只使用了 data2 ,那么其实代码中只有 data2getData2 是有效函数,其他的代码其实是无效的。

vue-hook-optimizer 支持分析组件中代码的使用情况,并给出优化的意见,比如针对上面的代码,就会生成下面这样的结果。

image.png

无效的链式调用

为了能够提高代码的可读性,我们一般会把较为独立和重复的部分抽象独立出来作为单独的模块,比较常见的做法比如我们会把 api 接口统一整理在一起,便于组件调用。这是一个非常好的思路,但是在编写代码的过程中,我们也可能会产生过多的无效的抽象,比如抽象的模块职责过于简单或过于复杂,或者代码的可复用性不强等。我们看一个简单的例子。

<script setup lang="ts">

const baseDate = new Person()

function getData1() {
  return baseDate
}

function getData2() {
  return getData1()
}

const data2 = getData2()

const date3 = computed(() => data2)

</script>
<template>
  <div> {{date3}} </div>
</template>

在这个例子中,getData2和getData1其实做了无效的抽象,他们的职责过于简单,并且没有其他代码依赖这两个抽象,那么这两个函数其实是没有必要的。vue-hook-optimizer 能够针对链式调用提供一定的优化建议。

image.png

耦合的逻辑

vue3 和 react 可以使用 composition-api 或者 hook 的范式进行代码的编写,这非常便于我们梳理代码的逻辑,并且更易于测试和复用。但是和 vue2 的 options api 不一样,代码允许放在一起就一定会存在代码耦合在一起的情况。这里给一个我工作中的例子给大家参考看下。

image.png

这是我在工作中经常遇到的情况,代码逻辑复杂并且耦合程度很高。比如在图中,左下角有几个独立的灰色节点,这说明这些代码并没有在模板或者方法中被使用;在右侧复杂的调用链里,也存在几个灰色的节点,这些是没有暴露到模板中的内容,在组件的代码中将他们屏蔽掉是更好的选择。

image.png

在建议中提示了几个节点为重要节点,说明它们是代码中的关键路径,这些节点报错或者异常可能会阻断代码的逻辑。优化这些节点能够提高整体的稳定性。

特别的,在 vue-hook-optimizer 提供的建议中高亮了一个循环依赖。代码逻辑中 refresh 方法会调用 getList 获取数据并复制给 searchDeptList 。但是同时 searchDeptList 的变化会在 watch 中触发 refresh 方法,这是非常危险的,需要做好边界情况的处理避免做成无限循环。

根据提供的建议,有30个节点的内容耦合度高,需要我们手动对代码进行优化。比如在这个例子中可以将耦合的代码划分为 处理筛选模块、获取数据模块、处理数据模块。vscode 提供很方便的重构代码的能力,比如支持 重命名符号 重构到新文件 等能力。

image.png

这里再放一个代码逻辑比较清晰的情况下,vue-hook-optimizer 提供的可视化图示。

image.png

在这张图中,代码的逻辑虽然比较复杂,但是整体上还是可以区分成两个大的模块的,这说明代码结果是清晰的、易懂、易于维护的。

总结

维护旧代码一直被认为是吃力不讨好的工作,就像是大家调侃时说的「代码和人有一个能跑就行」。但是我认为,一个富有责任心的开发者,是需要反复推敲业务逻辑,反复打磨自己手里的代码,找出其中的薄弱环节并有针对性地优化。这也是我开发 vue-hook-optimizer 的初衷,我希望能够帮助更多的人更好地梳理和优化自己手里的代码。

最后,如果你认同我的观点,那么不妨现在就打开 vscode 安装 扩展 ,然后从第一个文件开始检查和优化吧。如果你有什么好的意见或建议,欢迎到 github 去提 issues ,我都会尽快回复。

闽 ICP 备 2021009779 号 - 1 | Copyright © 2020 华丽 | Powered By Hugo