我不想再翻代码找export了, 所以

写前端, 还是要解决自己需求才好玩。

起因

当我快乐的CRUD的时候,我注意到了一个很没意义的操作:

  1. 当写src/view/xxxx文件时
  2. 总会跑到src/http/api/xxxx 或者 src/tools/xxx 文件, 去看看那个文件 export 的变量名
  3. 然后切回src/view/xxxx 来写 import xxx from 'xxxx'.
  4. 重复 1-3 N次

我感到疲惫,所以我在想有没有更方便的方式。 比如文件目录中,展示这个文件的exports

然后还能直接拖拽, 拖拽时顺便带上import xxx from xxx

开整

于是我开始研究vscode插件的开发教程, 打开官方文档,霍,很简单嘛,也就两句命令. code.visualstudio.com/api/get-sta...

接下来就是漫长的调研学习,不得不说vscode插件资料比较少,参考了下面的教程:

学完发现,其实重要的就是两个逻辑:

  1. 遍历文件目录
  2. AST分析脚本

逻辑1就不说了,比较常规(常规到我直接用chatgpt生成), 大致如下:

javascript 复制代码
async getDirectory(message) {
    const directory = message.data.path
    const entries = await vscode.workspace.fs.readDirectory(vscode.Uri.file(directory))
    const resultPromise = entries.map(async ([name, type]) => {
      const filePath = path.join(directory, name)

      if (this.ignore.check(filePath, message.data.root))
        return
      const item: FileItem = {
        id: filePath,
        path: filePath,
        title: name,
        fileType: type === vscode.FileType.Directory ? 'Directory' : 'File',
        leaf: false,
        root: message.data.root,
      }
      if (type === vscode.FileType.File) {
        const extname = path.extname(filePath).replace('.', '')
        item.fileExt = extname
        if (!['js', 'tsx', 'jsx', 'ts'].includes(extname))
          return
      }
      if (type === vscode.FileType.Directory)
        item.children = []
      return item
    })

    const results = await Promise.all(resultPromise)
    return [0, results.filter(item => item)]
  }

核心还是在逻辑2上,想了想可能有两个办法:

  1. 通过动态import,进行运行时分析
  2. 通过Bable的AST进行静态语法分析

哪么选择哪一个逻辑更好呢? (小孩子才做选择,大人我全都要 !)

  • 对于动态 import,经朋友推荐,调研使用了 antfu 大佬开源的 pkg-exports 以及 local-pkg 库。
  • 对于BabelAST,找到了以下资源学习:

大致流程就是先babel.parser,再babel.traverse,最后分析AST就完事:

js 复制代码
export async function solveExports(code) {
    const ast = parser.parse(code, {
      sourceType: 'module',
      plugins: ['jsx', 'typescript', 'decorators'],
      errorRecovery: true,
    })
    const exports: any = []
    traverse(ast, {
      ExportDefaultDeclaration(astPath: any) {
        const returnType = solveDetail(astPath)
        exports.push({
          name: 'default',
          type: astPath.node.declaration.type,
          returnType: returnType?.type,
          children: returnType?.children,
        })
      },
      ExportNamedDeclaration(astPath: any) {
        const specifiers = astPath.node?.specifiers || []
        specifiers?.forEach((specifier: any) => {
          exports.push({ name: specifier.exported?.name, type: specifier.exported?.type })
        })
        const returnType = solveDetail(astPath)
        exports.push({
          name: astPath.node?.declaration?.id?.name,
          type: astPath.node?.declaration?.type,
          returnType: returnType?.type,
          children: returnType?.children,
        })
      },
    })
    return exports
  }
}

最后就是漫长的踩坑,写业务逻辑和业务调试,我后续再依次更新。

  • 比如如何配置工程化
  • 比如如何用solidjs开发webview
  • 比如支持vue,调研学习了vue-compiler
  • 比如分析出export的变量类型,以方便导入import
  • 等等等等

进度

目前感觉初步解决自己的需求,已发布体验版到VSCode商店.

VScode 插件商店搜索 XMouse 即可使用(也可以点击下方链接)

marketplace.visualstudio.com/items?itemN...

未来

  • 准备进一步分析文件export,以方便更好的使用。
  • 准备集成VSCode原生文件目录的核心功能,就不用来回切换面板。
  • 等等等等,期待建议

最后

我是尘码,曾鹅厂打工5年,现裸辞自由职业家里蹲 ing.

如对 Xmouse 有兴趣,欢迎私聊or提issue

XMouse github link

相关推荐
hhcccchh5 分钟前
1.2 CSS 基础选择器、盒模型、flex 布局、grid 布局
前端·css·css3
专吃海绵宝宝菠萝屋的派大星1 小时前
使用Dify对接自己开发的mcp
java·服务器·前端
爱分享的阿Q1 小时前
Rust加WebAssembly前端性能革命实践指南
前端·rust·wasm
蓝黑20201 小时前
Vue的 value=“1“ 和 :value=“1“ 有什么区别
前端·javascript·vue
小李子呢02111 小时前
前端八股6---v-model双向绑定
前端·javascript·算法
He少年1 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
史迪仔01121 小时前
[QML] QML IMage图像处理
开发语言·前端·javascript·c++·qt
AwesomeCPA1 小时前
Miaoduo MCP 使用指南(VDI内网环境)
前端·ui·ai编程
前端大波1 小时前
前端面试通关包(2026版,完整版)
前端·面试·职场和发展
qq_433502182 小时前
Codex cli 飞书文档创建进阶实用命令 + Skill 创建&使用 小白完整教程
java·前端·飞书