前言 在实际的开发中,经常会用到vue-devtools插件去快速的的打开组件的源码,但是对它的实现逻辑不是很清楚。官网给出的定义是:Vue Devtools 是 Vue 官方发布的调试浏览器插件,可以安装在 Chrome 和 Firefox 等浏览器上,直接内嵌在开发者工具中,使用体验流畅。 目前该插件有两个版本,支持Vue3的Beta版本,和支持Vue2的版本。
学习目标: 1 如何调试源码; 2 了解vue-devtools插件是如何在浏览器中直接通过编辑器打开组件; 3 vue-devtools的底层原理; 4 通过对源码的阅读,扩展对源码中优秀代码的认知;
1 如何调试代码(Vscode)
打开项目下的package.json页面,点击调试,并在下拉框中选择serve,然后系统会默认打开终端执行npm run serve脚本命令启动调试项目。
2 准备工作
vue-devtools是vue框架自带的一个插件,当我们用vue-cli创建Vue项目时,该插件会包含在node_modules中。这里创建一个新的项目
vue create demo-project
npm install
3 源码分析
3.1 vue-devtools是如何打开源码的
打开组件源码的方式
当我们点击打开App.vue组件时,可以在network中看到,会执行http://localhost:8080/__open-in-editor?file=src/App.vue请求。我们将http://localhost:8080/__open-in-editor?file=src/App.vue地址放到浏览器地址栏直接访问,可以直接打开对应的源码
以下源码解析都以打开http://localhost:8080/__open-in-editor?file=src/App.vue为例
3.2 入口文件
有了打开地址,我们就可以根据这个地址去查找入口文件
我们去源码中看第一个识别__open-in-editor是serve.js文件
3.3 launch-editor-middleware中间件
在==launch-editor-middleware==中间件中,接收传过来的参数,并最终调用==launch-editor==中间件 接收传过来的参数specifiedEditor, srcRoot, onErrorCallback
onErrorCallback = 当specifiedEditor或srcRoot为函数时赋值 srcRoot是传递过来的参数,或者当前node进程的目录
这里其实用了参数切换,我们可以看到launchEditorMiddleware函数接受了三个虚参,但实际用户调用可能就想传一个参数,而且是传给第二个虚参的,这个时候就可以根据第一个参数的参数类型做判断,来确认用户传的这个参数其实是给指定的虚参的。
比如这里如果第一个参数specifiedEditor如果是函数,则表示用户其实想赋值给onErrorCallback的,则切换参数。
3.4 launch-editor中间件
launchEditor函数接收三个参数,第一个参数为当前目标文件的绝对路径,第二个是编辑器,第三个错误处理函数。
我们打断点看一下函数内部。
3.4.1 parseFile
parseFile函数就是解析并提取文件路径、行号、列号的
// 对file文件路径处理:
const parsed = parseFile(file)
let { fileName } = parsed
const { lineNumber, columnNumber } = parsed
const positionRE = /:(\d+)(:(\d+))?$/
function parseFile (file) {
const fileName = file.replace(positionRE, '')
const match = file.match(positionRE)
const lineNumber = match && match[1]
const columnNumber = match && match[3]
return {
fileName,
lineNumber,
columnNumber
}
}
3.4.2 wrapErrorCallback
在onErrorCallback错误函数的基础上,再打印更多的错误日志
function wrapErrorCallback (cb) {
return (fileName, errorMessage) => {
console.log()
console.log(
colors.red('Could not open ' + path.basename(fileName) + ' in the editor.')
)
if (errorMessage) {
if (errorMessage[errorMessage.length - 1] !== '.') {
errorMessage += '.'
}
console.log(
colors.red('The editor process exited with an error: ' + errorMessage)
)
}
console.log()
if (cb) cb(fileName, errorMessage)
}
}
3.4.3 guessEditor
guessEditor的内部执行逻辑: 1、specifiedEditor是否指定编辑器,指定直接返回 2、specifiedEditor未指定
- 根据系统来创建不同子进程的sell命令
- 获取当前所有的进程
- 遍历进程信息的数组,获取到的进程最后的文件名和该系统预写的编辑器匹配,匹配上就返回
3.4.4 子进程child_process
child_process是node中用于创建子进程的内置模块,因为我们要打开指定文件,就需要新增一个子进程去执行。
4 总结
这是我第二次尝试进行源码阅读,总体来说比较吃力,阅读很慢,断点也不太会用,源码阅读能级亟待提高。就是现在感觉对这部分的源码还是没有完全的吃透,希望等以后源码能力上来了,再来重新的巩固一下,相信会有不一样的收获 参考网站 解锁vue-devtools的"隐藏"技能 vue-devtools 还能直接打开对应组件文件 vue-devtools 打开组件分析