前言
最近痴迷于AI编程助手,windsurf、MarsCode、通义灵码、cursor等,都或多或少体验过,由于住的地方网络一般,科学上网比较困难,MarsCode 用的最多,工作工程中也频繁使用,代码补全和生成功能甚得我心,万万没想到的是前段时间借助 MarsCode,机缘巧合下整了个大优化,解决了一个顽固的生产环境问题,项目加载速度提升 20% 以上,发了,年终奖这不得++。
经历过此次优化后,进一步加深了对于 MarsCode 的重视,在拥有一些基础知识前提下,AI 编程助手的天花板真的无限高,一方面要发掘到场景,例如花生大佬的小猫补光APP,荣升IOS付费榜top1;另一方面要多体验,总结使用方法。
下面介绍一下问题背景和利用 MarsCode 的解决思路:
当前的项目的粒度为活动开发,开发的活动通过 webview 嵌入到 app 中,活动业务开发起来相对不是特别复杂,页面整体基于绝对定位进行开发,使用自研组件库,其中有两个应用于布局的核心组件 a-section 流体块和 a-position 绝对定位块,高频使用,超高频。
业务中所有的布局都是基于 a-section 和 a-position,这就造成一个非常大的麻烦,页面中引入了大量的vue 组件,导致页面加载性能会非常差,造成部分活动用户的流失。
自 Q3 以来,同事们反复在讨论应对 section 和 position 方案,每次听大家的讨论一直都没有定位到核心问题上,每次都是听了个热闹,但是有一天晚上回到家,打开 MarsCode 那一刻,时间线发生了偏转。
解决过程
MarsCode 近期新增了 workspace 功能,输入带有 #Workspace
时,MarsCode 将自动从仓库中检索与提问相关的代码信息作为上下文,结合整个项目代码仓库进行回答。
workspace 功能,来者不善啊,借助它,可以实现对本地代码的解读和分析,就比如,当时的灵光乍现、奇思妙想
MarsCode 回复非常完善,很全面,但我非常敏捷的捕获到了四个关键字:性能优化
设想,在完全不了解项目上下文的前提,通过几秒的分析总结出此问题,可见这个问题多么严重啊,而且看到 页面加载性能可能存在问题,特别是在使用了大量 a-section 和 a-position 元素的情况下,也明白了一直讨论去 section 和 position 的意义。
大量的 vue 组件阻塞了页面的渲染,简单思考就有两种解决方案:
- 直接不使用,在 Q3 季度末,几位同事体验了使用纯 div 的开发模式,非常不习惯,况且现在有的组件基建很多都是基于 a-section 和 position 实现的,在业务高峰期,特别短暂的时间内有些不切实际
- 仍旧使用,设法提高渲染的效率,这个方面苦苦探索,一直没能够找到非常好的解法
就比如这里使用 MarsCode 进行反复询问,一时也没有得到比较满意且合适的解决方案。
造成 MarsCode 混乱原因非常简单,就是不知道具体的解决方式是什么,导致输入的提示词不专业、模棱两可,且 MarsCode 更擅长于 AI 编程,而不是 AI 交互。
这时候,想到了老朋友豆包,当时隐隐有种感觉,如果 html 中能直接渲染 a-section,直接不进行转换,是不是就万事大吉了?
于是将上述的想法凝练了一番,输入到豆包中:
自定义元素很早前在社区就有所耳闻过,可惜没有深究过,遇到问题时苦苦想不到。
找到解决方案了,可以继续借助 MarsCode 进行代码生成。
输入:由于需要将vue组件 a-section 和 a-position 定义为 custom element,首先需要实现一个baseCustomElement,用来作为基类
class baseCustomElement extends HTMLElement {
constructor() {
super();
// 初始化 Shadow DOM
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
// 当元素被插入到 DOM 中时调用
console.log('Custom element connected to DOM');
}
disconnectedCallback() {
// 当元素从 DOM 中移除时调用
console.log('Custom element disconnected from DOM');
}
attributeChangedCallback(name, oldValue, newValue) {
// 当元素的属性发生变化时调用
console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);
}
adoptedCallback() {
// 当元素被移动到新的文档时调用
console.log('Custom element moved to a new document');
}
}
// 注册自定义元素
customElements.define('base-custom-element', baseCustomElement);
自定义元素的核心逻辑实现了,还附上比较完善的煮食,缺一些针对于特定项目的适配,仍旧借助 MarsCode 提供思路。
对于专业性特别强的知识,以 MarsCode 为辅主,作为自己实现思路的补充和解读
将自定义元素适配到项目中,有两个核心点需要解决
- 封装 aTapInit 方法:为 DOM 元素挂载自定义 a-tap 事件和节流 throttleTime
- 如何将自研组件库的常用属性同步到自定义元素上
第一个问题比较好解决,第二个复杂一些,MarsCode 并不知道自研组件库中有哪些自定义的属性,这里凭借 MarsCode 一步到位比较困难。相较于写详细的提示词,还是选择使用 MarsCode 提供实现思路:
重点关注红色部分,只需要提供一个自定义属性和 style 属性的映射,然后更新相应的属性值。
将上面的思路进行完善,baseCustomElement 大约写了 150 行左右,基于 baseCustomElement 创建 Position 和 Section 类。
export default class Section extends baseCustomElement {
constructor() {
super()
}
}
由于只修改了自研组件库中的 section 和 position 组件,需要特殊处理一下,在 beforeEach 守卫中,进行拦截,替换 section 和 position 组件为定义好的自定义元素。
在 MarsCode 和 豆包的辅助下,当前优化的整体代码实现不超过 200 行,据数分同学反馈,应用自定义元素后,提效达 20% 以上,狂喜啊。
新的问题
自定义元素使用确实非常顺畅,无缝切换,但是在使用的过程中,出现了一个新的问问题:使用 v-if、v-else 的 vue 元素,在切换状态时会出现样式混乱的情形,莫名其妙的会借用别的元素的样式。具体原因还没有排查出来,解决方案也是后续询问 MarsCode 给的:
只能先使用添加 key 值的方式进行后天 fix,算是提升加载速度的副产物,问题总是要解决的,使用#workspace
分析询问 MarsCode,得到了一个非常想不到的回答:可能是 aTapInit 部分事件切换的时候,class 类名加载顺序存在问题。
这一点非常启发,样式混乱具体表现为错用其他元素的样式,感觉很可能是 class 切换错误引起的,后续会持续排查这个问题,如果暂时找不到问题,就只能借助 MarsCode 写一个 webpack loader,自动为 v-if 和 v-else 元素添加唯一key值。
兄弟们,如果有遇到类似情形的,欢迎留言讨论啊。
总结
很感慨,其实根本没有想到,使用 AI 编程助手真的解决了一个非常繁琐的、顽固的问题,借助 MarsCode + 豆包,可以突破自己的局限,更广阔的打开视野,编程的上限被拉高了,下限也被降低了,利在千秋啊。复盘来看,代码实现也比较简单,达成的效果却是非常卓越的,已经在幻想年终怎么花了。
经过本次优化,又有了些新的体验
- 一定要描述清晰需求,如果确实不知道怎么描述需求,可以反复的使用豆包或者 MarsCode 进行尝试,聊死了,就再开一个对话,继续聊
- 可以使用 MarsCode 作为辅助,以此提供丰富的思路,不指望它能一步完成,可以在它的引导下,自己不断完善自己的想法
- 不要惧怕麻烦,AI 编程助手的能力足以覆盖 90% 以上的情形,大胆尝试