Chrome插件vue-devtools是如何把VSCode中对应的组件文件打开的

简介: 点击如图所示的图标,就是打开对应的组件文件。可能初次使用,点击好几次都没有响应,然后返回到VSCode编辑器后发现,如下图所示的错误,该怎么办呢?

image.png


前言


通过本文可以学到哪些知识?


  1. 如何在Chrome中安装vue-devtools插件
  2. 创建vue3 demo项目,并调试一键打开对应组件文件
  3. 通过关联图可清晰整个流程的大体脉络
  4. 通过源码解剖原理
  5. vite项目如何进行调试使用
  6. 我为什么看源码?以及看源码能学到什么呢?


1、安装Chrome浏览器扩展插件vue-devtools


1、打开Chrome浏览器,点击最右侧`三个点`
2、点击:更多工具
3、继续点击:扩展程序
4、然后点击:页面左上角`三横杠`
5、继续点击:打开Chrome 网上应用店
6、然后搜索框输入:`vue`
7、出现列表:选择'Vue.js devtools (https://vuejs.org)',点击此项进入
8、然后点击`添加至Chrome`
9、出现弹框后,点击`添加扩展程序`,执行完,便添加完毕


注意了,这个插件也就是在开发的时候可以使用哟。


2、创建项目并测试


// 更新脚手架
npm update -g @vue/cli
//查看版本
vue -V // 5.0.8,此版本下不需要配置任何便可调试打开对应组件文件
// 创建项目
vue create vue3-ts-demo
// 选择一系列的模版组合,创建完毕,并安装依赖
// 直接通过VSCode打开此项目
// 直接运行
npm run serve


浏览器打开页面


image.png


会发现浏览器调试右侧出现一个标签页vue


image.png


点击如图所示的图标,就是打开对应的组件文件。可能初次使用,点击好几次都没有响应,然后返回到VSCode编辑器后发现,如下图所示的错误,该怎么办呢?


image.png


我现在使用的mac电脑,在VSCode中尝试快捷键command + shift + p,如果是window电脑可能是 Ctrl + Shift + p,然后输入shell,选择安装code。如下图:


image.png


选中安装Code命令后,重新运行项目,然后再次点击如图箭头所示位置


image.png


就会跳转到VSCode并打开对应的组件文件


image.png


原理:其实就是通过code命令,进行打开对应的文件,你可以在项目根目录进行测试code package.json或者其他文件,稍等片刻便会打开该文件。


3、一图胜千言


其实调试完上面的代码以后,我才开始想这其中的原理到底是怎么实现的,心里还在嘀咕有那么神奇吗?


其实作为菜如鸡的我一开始还真想不明白,于是我不断的阅读源码,一步一步的揭开了神秘的面纱,后来才发现也不过尔尔。


image.png


这里需要搞清楚几个小问题,也是我在梳理的过程中花费时间比较长的疑惑。


1.vue-devTools也算是Chrome插件,是Chrome DevTools扩展,开发者工具里面的Tab扩展页


2.点击按钮发送的请求,然后通过webpack里的devServer进行请求拦截


3.请求拦截后,调用尤大大写的小插件 launch-editor


4.而launch-editor最终调用的child_process.spawn来执行命令


5.最终执行vscode中的code命令(我上面写过如何去安装)


4、从源码的角度解剖原理


4.1、准备工作


  • vue-devtools chrome浏览器插件已经安装


  • 过vuecli 创建好了vue3的项目

4.2、vue-devTools 插件中点击按钮


查看的代码当然就在devtools


按钮的模版代码


<VueButton
  v-if="fileIsPath"
  v-tooltip="{
    content: $t('ComponentInspector.openInEditor.tooltip', { file: data.file }),
    html: true
  }"
  icon-left="launch"
  class="flat icon-button"
  @click="openFile()"
/>
// tooltip显示的字符串
ComponentInspector: {
  openInEditor: {
    tooltip: 'Open <mono><<insert_drive_file>>{{file}}</mono> in editor',
  },
},


通过代码可以发现按钮事件openFile


function openFile () {
    if (!data.value) return
    openInEditor(data.value.file)
  }


可以看到里面又调用了openInEditor


export function openInEditor (file) {
  // Console display
  const fileName = file.replace(/\\/g, '\\\\')
  const src = `fetch('${SharedData.openInEditorHost}__open-in-editor?file=${encodeURI(file)}').then(response => {
    if (response.ok) {
      console.log('File ${fileName} opened in editor')
    } else {
      const msg = 'Opening component ${fileName} failed'
      const target = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {}
      if (target.__VUE_DEVTOOLS_TOAST__) {
        target.__VUE_DEVTOOLS_TOAST__(msg, 'error')
      } else {
        console.log('%c' + msg, 'color:red')
      }
      console.log('Check the setup of your project, see https://devtools.vuejs.org/guide/open-in-editor.html')
    }
  })`
  if (isChrome) {
    target.chrome.devtools.inspectedWindow.eval(src)
  } else {
    // eslint-disable-next-line no-eval
    eval(src)
  }
}


其中主要的代码便是src变量的赋值,以及通过eval或者target.chrome.devtools.inspectedWindow.eval来执行src字符串。


src变量中的代码,不看错误处理的代码,其实也非常简单 就是一个fetch请求,其中变量SharedData.openInEditorHost就是一个/


fetch(`/__open-in-editor?file=${encodeURI(file)}`).then(response => {
    if (response.ok) {
      console.log('File ${fileName} opened in editor')
    } else {
      const msg = 'Opening component ${fileName} failed'
    }
  })


这里最重要的其实就是这个请求路径__open-in-editor


4.3、再来看我们创建的demo项目vue3-ts-demo


通过一个截图来看看代码位置


image.png


代码其实是在node_modules/@vue/cli-service../serve.js,也就是运行一下命令后执行的脚本代码


"serve": "vue-cli-service serve",


执行完上述命令,会将__open-in-editor请求地址注册到devServer,后续如果有请求过来,地址刚好一样,便会调用下面的launchEditorMiddleware,并传递了一个匿名函数。


const launchEditorMiddleware = require('launch-editor-middleware')
// .....省略很多暂时用不到的代码
devServer.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`
)))


4.4、中间件launch-editor-middleware


上面launchEditorMiddleware最终使用的便是该npm包,里面只有一个文件,代码如下所示


const url = require('url')
const path = require('path')
const launch = require('launch-editor')
module.exports = (specifiedEditor, srcRoot, onErrorCallback) => {
  // specifiedEditor 传递进来的cnsole.log匿名函数
  // srcRoot和onErrorCallback都为undefined
  if (typeof specifiedEditor === 'function') {
    onErrorCallback = specifiedEditor
    specifiedEditor = undefined
  }
  if (typeof srcRoot === 'function') {
    onErrorCallback = srcRoot
    srcRoot = undefined
  }
  // 获得当前执行node命令时候的文件夹目录名 
  // /Users/user/Desktop/aehyok/github/demo/vue3-ts-demo
  srcRoot = srcRoot || process.cwd()
  // 初始化先,并不执行
  return function launchEditorMiddleware (req, res, next) {
    const { file } = url.parse(req.url, true).query || {}
    if (!file) {
      res.statusCode = 500
      res.end(`launch-editor-middleware: required query param "file" is missing.`)
    } else {
      launch(path.resolve(srcRoot, file), specifiedEditor, onErrorCallback)
      res.end()
    }
  }
}


这里初始化的时候,并不会执行return function launchEditorMiddleware。等到下次有请求为__open-in-editor的时候,才会真正的调用 launchEditorMiddleware


4.5、点击open xxx path in editor


image.png


看顶部引用


const launch = require('launch-editor')


4.6、最后的执行函数 launch-editor


然后开始执行如下函数


function launchEditor (file, specifiedEditor, onErrorCallback) {
  // 最重要的是解析出文件名 
  const parsed = parseFile(file)
  let { fileName } = parsed
  const { lineNumber, columnNumber } = parsed
  // 判断次文件是否存在
  if (!fs.existsSync(fileName)) {
    return
  }
  // 根据guessEditor推断出当前使用的代码编辑器
  const [editor, ...args] = guessEditor(specifiedEditor)
  // 如果editor,则会报错
  if (!editor) {
    onErrorCallback(fileName, null)
    // 其中打印错误就是之前上面的截图
    // colors.red('Could not open ' + path.basename(fileName) + ' in the editor.')
    return
  }
  //... 中间忽略很多的代码
  // window系统下调用cmd命令行工具执行code
  if (process.platform === 'win32') {
    // On Windows, launch the editor in a shell because spawn can only
    // launch .exe files.
    _childProcess = childProcess.spawn(
      'cmd.exe',
      ['/C', editor].concat(args),
      { stdio: 'inherit' }
    )
  } else {
    // 其他平台则直接使用nodejs中childProcess模块的spawn,来执行code命令行
    _childProcess = childProcess.spawn(editor, args, { stdio: 'inherit' })
  }
}


至此整个调试的大致过程已经清晰明了了,不知道你看懂了没,如果没看懂,一定是我没表述清楚,不过整个思路我已经了然于胸了。


5、通过vite 创建测试项目


// 创建项目
pnpm create vite
//项目名称
vite3-vue3-demo
// 选择框架
vue
// 选择一个变体
vue-ts
//OK,项目创建完毕,安装依赖
pnpm i
// 运行项目
pnpm dev


这里我试过好几个办法都没有解决去给process.env.EDITOR赋值,可能是我打开方式不对,如果有看我文章有解决方案的,可以告知菜鸡一下,非常感谢。


我这里就是直接修改node_modules中launch-editor中的guess.js


// Last resort, use old skool env vars
  if (process.env.VISUAL) {
    return [process.env.VISUAL]
  } else if (process.env.EDITOR) {
    return [process.env.EDITOR]
  }
  return [null]


将最后的return [null]改为 return ['code'],其实就是上面的process.env.EDITOR不知道如何赋值,我尝试了两种方式去修改,都没成功,这其中原因我还没找出来???


6、总结


通过调试源码发现,只要仔细一点稍微花点时间,原来也能看懂尤大写的代码,没有想象中的那么难,而且感觉逻辑非常清晰,阅读起来很优雅。所以大家如果有想看源码,或者参加若川源码共读活动的,一定要大胆一些,不要怂,事情真的没有那么难。


有点目的性的阅读源码似乎更高效,这样针对性很强,不会大一统所有的源码都会过一下,时间一下子就过去了,每次带着一个小问题去看源码或许也是若川大佬的精髓所指。


通过阅读源码,就是把看不懂的函数方法关键字等,不断的查漏补缺。或者在这里的用法或者写法不一样,等等各种超乎你想象的用法、场景...,收获真的是非常大,尤其是看完后再写一篇小文总结出来,真的就比读一遍别人写的收获要多好几倍的感觉。


所以如果你还在犹豫自己看不懂,自己行不行等等借口,作为一个前端还不到两年经验的人告诉你,加加油相信自己,你完全可以的。最后一定要行动起来。


写的文章不要总想着有好多好多的浏览量,又或者有几十几百上千的点赞,我的要求不高,首先是自己真的学到了,思路真的整理总结出来了,那么自己在遇到同样问题的时候回看也是非常的方便的。最后送给有需要的人士,哪怕只有一位同仁看了我的文章,也就证明了它的价值所在。


谢谢在看的朋友,欢迎你一起来参加源码共读活动,学习真是一件快乐的事情,尤其是真的学到了,而不是浑浑噩噩的在混日子,当然自己之前浪费过太多的时间,假以时日,我定会.......

目录
相关文章
|
3月前
|
自然语言处理 API C++
阿里通义推出SmartVscode插件,自然语言控制VS Code,轻松开发应用,核心技术开源!
SmartVscode插件深度解析:自然语言控制VS Code的革命性工具及其开源框架App-Controller
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
|
7天前
|
人工智能 自然语言处理 前端开发
通义灵码插件在VSCode中的运用
借助通义灵码插件在VSCode构建新闻网,实现效率与智能的融合。VSCode作为前端开发的“瑞士军刀”,提供实时预览、智能辅助和高效管理功能;通义灵码插件通过自然语言交互生成代码,简化复杂任务并优化代码质量。两者结合形成从设计到部署的高效闭环,大幅减少基础编码时间,降低开发门槛,助力开发者聚焦业务逻辑与创新。
|
15天前
|
人工智能 小程序 程序员
【视频测评 DEMO 参考】VSCode 神级 AI 插件通义灵码:完全免费+实战教程+微信贪吃蛇小程序
VSCode 神级 AI 插件通义灵码:完全免费+实战教程+微信贪吃蛇小程序
252 7
|
1月前
|
Web App开发 存储 开发者
Chrome 插件上架发布全流程指南
浏览器插件开发完以后,要发布到 Chrome Web Store上,也是需要颇费一番周折的,本文就从注册账号开始,一直到最后发布上架的全流程进行指导,希望帮助你提供一些经验,避免踩坑,耗时耗力。
269 8
|
3月前
|
开发工具 C++ git
利用VS Code提升开发效率的五大插件推荐
本文推荐了五款能显著提升开发效率的VS Code插件:ESLint用于代码质量和风格检查;Prettier自动格式化代码;GitLens增强Git功能;Live Server提供前端实时预览;Docker支持容器管理。
|
4月前
|
自然语言处理 JavaScript 开发者
通义灵码插件:VSCode 的智能编程助手
通义灵码插件:VSCode 的智能编程助手
2080 3
|
4月前
|
前端开发 JavaScript 编译器
2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
【10月更文挑战第11天】2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
1153 0
2024最新VSCode实用插件推荐,开发效率遥遥领先!超全面,快收藏~
|
4月前
|
Web App开发 JSON JavaScript
vue学习:chrome 中 vuetools 开发插件 的下载、安装
这篇文章介绍了如何在Chrome浏览器中下载、安装并测试Vue.js开发插件——vue-devtools。
767 0
vue学习:chrome 中 vuetools 开发插件 的下载、安装
|
JavaScript
Vue的非父子组件之间传值
全局事件总线 一种组件间通信的方式,适用于任意组件间通信
100 0

热门文章

最新文章