前言
vue-devtools点击就可以在IDE中打开对应组件文件,这是什么魔法?本文一探究竟。
先上图:
环境准备
-
vue-devtools 按照文档安装浏览器插件。
-
vue-cli使用vue-cli搭建一个vue项目,安装好依赖。
-
vscode设置code命令配置
-
vscode开启debugger,运行vue项目
vscode设置code命令
-
cmd + shift + p
-
输出shell
施法
vue-devtools点击app.vue的位置,追溯app.vue是怎么打开的
WebpackDevServer开启服务监听
vue-cli-service serve
-
上面执行node_modules/@vue/cli-service/lib/commands/serve.js
-
如下图给/__open-in-editor路径绑定launchEditorMiddleware事件
-
按钮其实对应地址就是http://localhost:8080/__open-in-editor?file=src/App.vue
Tips: vscode可点击名称,鼠标右键,选择转到定义可直接跳转到定义的位置
before (app, server) {
// 通过 http://localhost:8080/__open-in-editor?file=监听打开文件服务(取query中的file)
app.use('/__open-in-editor', launchEditorMiddleware(() => console.log(
`To specify an editor, specify the EDITOR env variable or ` +
`add "editor" field to your Vue project config.\n`
)))
// allow other plugins to register middlewares, e.g. PWA
api.service.devServerConfigFns.forEach(fn => fn(app, server))
// apply in project middlewares
projectDevServerOptions.before && projectDevServerOptions.before(app, server)
}
launchEditorMiddleware
通过回调参数寻找文件,没有则抛出错误,结束服务。找到则通过launch寻找IDE命令执行
const launch = require('launch-editor')
// 省略若干
return function launchEditorMiddleware (req, res, next) {
// 例子:http://localhost:8080/__open-in-editor?file=src/App.vue
const { file } = url.parse(req.url, true).query || {} // src/App.vue
if (!file) {
res.statusCode = 500
res.end(`launch-editor-middleware: required query param "file" is missing.`)
} else {
// path.resolve('/Users/zhouguang/Desktop/own/vue/vue2', 'src/App.vue')
launch(path.resolve(srcRoot, file), specifiedEditor, onErrorCallback)
// 结束服务
res.end()
}
}
launch-editor
寻找IDE对应执行命令并且打开传入的文件
找文件
const parsed = parseFile(file)
// 完整文件路径:'/Users/zhouguang/Desktop/own/vue/vue2/src/views/docs/index.vue'
let { fileName } = parsed
const { lineNumber, columnNumber } = parsed
// 找不到则退出
if (!fs.existsSync(fileName)) {
return
}
错误回调函数包装处理
// 参数转移
if (typeof specifiedEditor === 'function') {
onErrorCallback = specifiedEditor
specifiedEditor = undefined
}
// 包裹函数,利于封装本身错误处理以及扩展外部错误处理
onErrorCallback = wrapErrorCallback(onErrorCallback)
寻找IDE对应code命令以及传参
const [editor, ...args] = guessEditor(specifiedEditor)
guessEditor
根据环境寻找IDE对应的执行命令,下面以mac + vscode为例:
ps x是返回unix所有安装的程序
osx.js
module.exports = {
// 省略。。。
'/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code'
// 省略。。。
}
// 引入mac中各IDE对应命令字典
const COMMON_EDITORS_OSX = require('./editor-info/osx')
// darwin对应unix系统
if (process.platform === 'darwin') {
// ps x log出程序列表
const output = childProcess.execSync('ps x').toString()
// 找出拥有的程序在osx对应的程序命令并返回
// '/Applications/Visual Studio Code.app/Contents/MacOS/Electron' => 'code'
const processNames = Object.keys(COMMON_EDITORS_OSX)
for (let i = 0; i < processNames.length; i++) {
const processName = processNames[i]
if (output.indexOf(processName) !== -1) {
return [COMMON_EDITORS_OSX[processName]]
}
}
}
继续回到launch-editor
// args加入完整路径.例子:/Users/zhouguang/Desktop/own/vue/vue2/src/App.vue
args.push(fileName)
// node子进程执行 code /Users/zhouguang/Desktop/own/vue/vue2/src/App.vue
_childProcess = childProcess.spawn(editor, args, { stdio: 'inherit' })
结束服务
// 结束服务
res.end()
总结
-
一句话流程:输入:/path/file,输出code /path/file
-
包装函数有利于封装自身处理函数以及处理回调
-
参数转移解决传参几个变成一个问题