vue-devtools打开文件的魔法之旅

1,553 阅读2分钟

前言

vue-devtools点击就可以在IDE中打开对应组件文件,这是什么魔法?本文一探究竟。

先上图:

D210017C-73E1-41F5-AB31-97A72765C763.png

环境准备

  1. vue-devtools 按照文档安装浏览器插件。

  2. vue-cli使用vue-cli搭建一个vue项目,安装好依赖。

  3. vscode设置code命令配置

  4. vscode开启debugger,运行vue项目

vscode设置code命令

  1. cmd + shift + p

  2. 输出shell

35582509-E640-4360-ABE3-0DEB85BA84D7.png

施法

vue-devtools点击app.vue的位置,追溯app.vue是怎么打开的

WebpackDevServer开启服务监听


vue-cli-service serve

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为例:

process.platform

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

  • 包装函数有利于封装自身处理函数以及处理回调

  • 参数转移解决传参几个变成一个问题

感谢

若川源码共读活动

据说 99% 的人不知道 vue-devtools 还能直接打开对应组件文件?本文原理揭秘