如何在 Vue 项目中,通过点击 DOM 自动定位 VSCode 中的代码行?
作者:vivo 互联网大前端团队- Youchen
一、背景
现在大型的 Vue 项目基本上都是多人协作开发,并且随着版本的迭代,Vue 项目中的组件数也会越来越多,如果此时让你负责不熟悉的页面功能开发,甚至你才刚刚加入这个项目,那么怎么样才能快速找到相关组件在整个项目代码中的文件位置呢?想必大家都有采取过以下这几种方法:
【搜类名】,在工程文件里搜索页面 DOM 元素中的样式类名
【找路由】,根据页面链接找到 Vue 路由匹配的页面组件
【找人】,找到当初负责开发该页面的人询问对应的代码路径
以上几种方法确实能够帮助我们找到具体的代码文件路径,但都需要人工去搜索,并不是很高效,那有没有其它更高效的方式呢?
答案是有的。Vue 官方就提供了一款 vue-devtools 插件,使用该插件就能自动在 VSCode 中打开对应页面组件的源代码文件,操作路径如下:
使用 vue-devtools 插件可以很好地提高我们查找对应页面组件代码的效率,但只能定位到对应的组件代码,如果我们想要直接找到页面上某个元素相关的具体代码位置,还需要在当前组件源代码中进行二次查找,并且每次都要先选择组件,再点击打开按钮才能打开代码文件,不是特别快捷。
针对这个问题,我们开发了轻量级的页面元素代码映射插件,使用该插件可以通过点击页面元素的方式,一键打开对应代码源文件,并且精准定位对应代码行,无需手动查找,能够极大地提高开发效率和体验,实际的使用效果如下:
二、实现原理
整个插件主要分为 3 个功能模块:client、server、add-code-location,client 端发送特定请求给 server 端,server 端接收到该请求后执行定位代码行命令,而 add-code-location 模块用于源码的转换。
2.1 client
client 端这里其实就是指浏览器,我们在点击页面元素时,浏览器就会发送一个特定请求给 server 端,该请求信息包含了具体的代码文件路径和对应代码行号信息。
而监听页面元素的点击事件则通过事件代理的方式全局监听,给 document 绑定了点击事件,监听键盘和鼠标点击组合事件来发起定位代码行请求,避免和页面原生的 click 事件发生冲突。
2.2 server
server 端是指本地起的一个服务器,可以监听 client 端发送的特定请求,当接收到执行定位命令的请求时,执行 VSCode 打开代码文件命令,并定位到对应的代码行。
2.2.1 webpack devServer
如果是采用 webpack 构建的项目,webpack 的 devServer 开发服务器已经提供了一个 before 属性,可以通过它来监听发送给开发服务器的请求。
2.2.2 vite configureServer
如果是采用 Vite 构建的项目,可以使用 Vite 插件来实现 server 端监听特定请求,Vite 插件扩展于 rollup 插件接口,并且在原有的基础上增加了一些特有的钩子函数,例如 configureServer 钩子,通过该钩子函数可以用于配置开发服务器来监听特定的请求。
2.2.3 执行 VSCode 定位命令
当 server 端监听到 client 端发送的特定请求后,接下来就是执行 VSCode 定位代码行命令。实际上,VSCode 编辑器是可以通过 code 命令来启动,并且可以相应使用一些命令行参数,例如:
"code --reuse-window"或"code -r"命令可以打开最后活动窗口的文件或文件夹;"code --goto"或"code -g"命令后面可以拼接具体文件路径和行列号,当使用"code -g file:line:column"命令时可以打开某个文件并定位到具体的行列位置。
利用 VSCode 编辑器的这个特性,我们就能实现自动定位代码行功能,对应的代码路径信息可以从 client 端发送的请求信息当中获得,再借助 node 的 child_process.exec 方法来执行 VSCode 定位代码行命令。
另外,为了正常使用 VSCode 的 Code 命令,我们需要确保添加 VSCode Code 命令到环境变量当中。Mac 系统用户可以在 VSCode 界面使用 command+shift+p 快捷键,然后搜索 Code 并选择 install 'code' command in path;Windows 用户可以找到 VSCode 安装位置的 bin 文件夹目录,并将该目录添加到系统环境变量当中。
2.3 add-code-location
通过前面的介绍,大家应该了解了 client 端和 server 端的执行机制,并且在执行定位命令时需要获取到页面元素的代码路径,而具体的代码路径是以属性的方式绑定到了 DOM 元素上,这时候就需要用到 add-code-location 模块在编译时转换我们的源码,并给 DOM 元素添加对应的代码路径属性。
整个源码转换处理流程如下:
2.3.1 获取文件路径
源码转换过程的第一步是获取代码文件的具体路径,对于 webpack 打包的项目来说,webpack loader 用来处理源码字符串再合适不过,loader 的上下文 this 对象包含一个 resourcePath 资源文件的路径属性,利用这个属性我们很容易就能获得每个代码文件的具体路径。
对于 Vite 构建的项目来说,源码的转化操作也是通过插件来完成,Vite 插件有通用的钩子 transform,可用于转换已加载的模块内容,它接收两个参数,code 参数代表着源码字符串,id 参数是文件的全路径。
2.3.2 计算代码行号
接着在遍历源码文件的过程中,需要处理对应 Vue 文件 template 模板中的代码,以“\n”分割 template 模板部分字符串为数组,通过数组的索引即可精准得到每一行 html 标签的代码行号。
2.3.3 添加位置属性
在获取到代码文件路径和代码行号以后,接下来就是对 Vue template 模板中分割的每一行标签元素添加最终的位置属性。这里采用的是正则替换的方式来添加位置属性,分别对每一行标签元素先正则匹配出所有元素的开始标签部分,例如<div、<span、<img 等,然后将其正则替换成带有 code-location 属性的开始标签,对应的属性值就是前面获取的代码路径和对应标签的行号。
2.4 其他处理
2.4.1 源码相对路径
在给 DOM 元素添加对应的源码位置属性时,实际上采用的是相对路径,这样可以使得 DOM 元素上的属性值更加简洁明了。node_modules 文件夹通常是在项目的根目录下,而插件是以 npm 包的形式安装在 node_modules 路径下,利用 node 的__dirname 变量可以获得当前模块的绝对路径,因此在源码转换过程中就可以获取到项目的根路径,从而就能获得 Vue 代码文件的相对路径。
在 server 端执行代码定位命令时,再将对应的代码相对路径拼接成完整的绝对路径。
2.4.2 外部引入组件
add-code-location 虽然可以对本地的 Vue 文件进行代码路径信息的添加,但是对于外部引入或解析加载的组件目前是没有办法进行转换的,例如 element ui 组件,实际上的代码行信息只会添加在 element ui 组件的最外层。这时候 client 端在获取点击元素的代码路径时会做一个向上查找的处理,获取其父节点的代码路径,如果还是没有,会继续查找父节点的父节点,直到成功获取代码路径。
这样就可以在点击后台 element ui 搭建的页面元素时,也能成功定位打开对应代码文件。
三、接入方案
通过前面的介绍,想必大家对页面元素代码映射插件原理有了清晰的了解,接下来就介绍一下在项目中的接入方式。接入方式其实很简单,并且可以选择只在本地开发环境接入,不用担心对我们的生产环境造成影响,放心使用。
3.1 webpcak 构建项目
对于 webpack 构建的项目来说,首先在构建配置项 vue.config.js 文件中配置一下 devServer 和 webpack loader,接着在 main.js 入口文件中初始化插件。
3.2 Vite 构建项目
Vite 构建项目接入该插件的方案和 webpack 构建项目基本上一致,唯一不一样的地方在于打包配置文件里引入的是两个 Vite 插件。
四、总结
以上就是对页面元素代码映射插件核心原理和接入方案的介绍,实现的方式充分利用了项目代码打包构建的流程,实际上无论是哪个打包工具,本质上都是对源码文件的转换处理,当我们理解了打包工具的运行机制后,就可以做一些自己认为有意义的事。就拿页面元素代码映射插件来说,使用它可以极大提升开发效率,不再需要花费时间在寻找代码文件上,特别是页面数和组件数比较多的项目,只需点击页面元素,即可一键打开对应代码文件,精准定位具体代码行,无需查找,哪里不会点哪里,so easy!
版权声明: 本文为 InfoQ 作者【vivo互联网技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/9b76c52607f2e8cdbb355bc14】。文章转载请联系作者。
评论