点击DOM元素跳转源码位置插件
# 图例
- 开发环境下,按住command键,点击元素,自动打开 vscode,并跳转到该 dom 对应的源码位置
 
  
 # 插件功能
- 在多人协作的项目里,如果有改 bug、改他人代码、改不熟悉的功能代码的场景,都能直接从浏览器快速定位到 VSCode 中的代码行,极大地提高了开发效率。
# 实现思路
- 生成 - fileMap.json文件,为项目中的所有文件创建了一个编号映射,并且存到这个文件中- 写一个方法 - getAllFiles,递归遍历项目目录,获取这个目录下所有文件的完整路径
- 写一个方法 - generateFileMap,使用- getAllFiles方法,为 src 下所有的文件生成一个映射 Map 并且保存到本地- fileMap.json文件里
 
- 实现插件 - vite-plugin-open-in-vscode- 初始化的时候,在 - configResolved钩子里面执行,当 Vite 项目配置解析完成后,如果当前环境是开发环境,插件会调用- generateFileMap生成- fileMap.json文件。确保了在开发过程中,- fileMap.json始终是最新的,包含了项目中所有文件的映射。- 需要注意的是,如果在一次开发过程中,如果新建了很多文件,需要重新yarn dev,才能生成这些新建文件的映射
 
- 需要注意的是,如果在一次开发过程中,如果新建了很多文件,需要重新
- 集成一个 - express服务,这个服务用来提供一个接口- http://localhost:6003/vscode/openfile,这个接口的主要作用是根据接口的参数- filePath和- lineNumber,通过- exec命令调用 vscode,从而打开指定文件- filePath定位到指定行- lineNumber- 这个接口会在开发环境下,通过开发者的特定操作(按住command的时候鼠标左边点击 dom 元素),获取该 dom 元素的data-sf和data-sl属性,触发请求vscode/openfile,其中 dom 元素的data-sf和data-sl属性就是接口的请求参数filePath和lineNumber
 
- 这个接口会在开发环境下,通过开发者的特定操作(按住
 
# 实现代码
点击 展开/收起 jsx 代码
import express from 'express';
import { exec } from 'child_process';
import fs, { readFileSync } from 'fs';
import path from 'path';
import { join } from 'path';
// 获取所有文件路径的函数
function getAllFiles(dirPath, arrayOfFiles = []) {
  const files = fs.readdirSync(dirPath);
  files.forEach((file) => {
    if (fs.statSync(path.join(dirPath, file)).isDirectory()) {
      arrayOfFiles = getAllFiles(path.join(dirPath, file), arrayOfFiles);
    } else {
      arrayOfFiles.push(path.join(dirPath, file));
    }
  });
  return arrayOfFiles;
}
// 生成文件映射的函数
function generateFileMap() {
  const allFiles = getAllFiles('./src'); // 遍历 src 目录下的所有文件
  const fileMap = {};
  allFiles.forEach((file, index) => {
    fileMap[index] = file;
  });
  fs.writeFileSync('fileMap.json', JSON.stringify(fileMap, null, 2));
}
export default function openInVSCodePlugin() {
  return {
    name: 'vite-plugin-open-in-vscode',
    configResolved(config) {
      if (process.env.NODE_ENV === 'development') {
        // 项目运行之前生成文件映射
        generateFileMap();
      }
    },
    configureServer(server) {
      const app = express();
      app.use(express.json());
      app.get('/vscode/openfile', async (req, res) => {
        const { filePath, lineNumber, columnNumber } = req.query;
        // 读取文件映射
        const fileMap = JSON.parse(
          readFileSync(join(process.cwd(), 'fileMap.json'), 'utf8'),
        );
        if (filePath && lineNumber) {
          exec(
            `code -g ${fileMap[filePath]}:${lineNumber}:${columnNumber || 1}`,
            (err) => {
              if (err) {
                console.error(`Error opening file in VSCode: ${err.message}`);
                res.status(500).send('Error opening file in VSCode');
                return;
              }
              res.send('File opened in VSCode');
            },
          );
        } else {
          console.error('Invalid filePath or lineNumber');
          res.status(400).send('Invalid filePath or lineNumber');
        }
      });
      app.listen(6003, () => {
        console.log(`Express server running on http://localhost:${6003}`);
      });
      server.middlewares.use(app);
    },
  };
}