阅读 503

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

前言

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 复制代码

  • 上面执行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为例:

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 还能直接打开对应组件文件?本文原理揭秘


作者:惜时自珍
链接:https://juejin.cn/post/7031053057798438948

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐