likes
comments
collection
share

项目功能太多,目录很乱怎么办?

作者站长头像
站长
· 阅读数 26

问题描述

随着我们项目的迭代,页面功能也是越来越多。慢慢的我们想要找到很久之前的功能就很费时间,尤其是英语不好或者前辈起名很随意的同学,想找原来的功能全靠全局搜索。如果项目菜单还是动态的那更是雪上加霜。

能不能有办法让人快速了解我们的项目结构。清晰的知道每个文件都是干什么的,让项目组的每个同学都对业务都有很清晰的了解,即使不是自己负责的也有大概的认知。

解决方案

快速找到需要的代码

想解决快速找代码的需求,最简单的方案就是安装一个vue devtools。如图所示,点击这个按钮 就会自动打开vscode,找到相应组件对应的代码。非常的方便

项目功能太多,目录很乱怎么办?

生成目录文件

项目功能太多,目录很乱怎么办?

项目功能太多,目录很乱怎么办? 我的做法是根据代码中的注释和文档生成一个大概这样的markdown文档,我们可以看到每个文件或者文件夹的解释说明。并且可以直接点击路径跳转到相应文件。

文件注释的添加与提取

文件中的注释我使用了vscode中的korofileheader插件,用于生成文件头部注释。大概这样

<!--
 * @Author: xxxx
 * @Date: 2022-08-07 08:50:19
 * @LastEditors:xxxx
 * @LastEditTime: 2022-09-19 15:27:50
 * @Description: 我是当前文件的描述
-->

settings.json的文件配置如下

  // 头部注释
  "fileheader.customMade": {
    "Author": "git config user.name && git config user.email", // 同时获取用户名与邮箱
    "Date": "Do not edit", // 文件创建时间(不变)
    "LastEditors": "git config user.name && git config user.email", // 文件最后编辑者 与Author字段一致
    "LastEditTime": "Do not edit", // 文件最后编辑时间
    "Description": "请输入文件描述", // 介绍文件的作用、文件的入参、出参。
  },
  "fileheader.configObj": {
    "autoAdd": true, // 检测文件没有头部注释,自动添加文件头部注释
    "autoAddLine": 1000, // 文件超过多少行数 不再自动添加头部注释
    "supportAutoLanguage": [
      "js",
      "ts",
      "vue",
      "css",
      "less",
      "html"
    ], // 设置之后,在数组内的文件才支持自动添加
    "createHeader": true, // 新建文件自动添加头部注释
    "throttleTime": 60000, // 对同一个文件 需要过1分钟再次修改文件并保存才会更新注释
  },

然后通过一段正则出来。来匹配到 @Description后面的文本。当做这个文件的解释说明。

文件夹注释的添加与提取

文件夹的注释来自于文件夹内的 README.md 文件。在代码中,当处理一个目录时,它会检查该目录下是否存在一个 README.md 文件。如果存在,它会读取该文件的内容,并尝试获取文件的第一行作为该目录的注释。同时最好可以在 README.md 文件中补充这个文件夹的具体作用,实现了哪些需求。

具体代码

// 导入必要的 Node.js 模块
import * as fs from 'fs'
import * as path from 'path'

// 定义一个数组,列出需要在 Markdown 中显示的文件类型
const validExtensions = [`.ts`, `.js`, `.vue`, `.less`, `.css`]

/**
 * 递归地生成指定目录的 Markdown 结构
 * @param {string} dir - 要处理的目录路径
 * @param {number} depth - 当前目录的深度,用于生成正确的缩进
 * @returns {string} - 生成的 Markdown 结构
 */
function generateMarkdownStructure(dir, depth = 0) {
  let result = ``

  // 读取目录中的文件和子目录,并筛选出有效的文件和子目录
  const files = fs.readdirSync(dir).filter(file => {
    const filePath = path.join(dir, file)
    const stats = fs.statSync(filePath)
    if (stats.isDirectory()) {
      return true
    } else {
      const fileExtension = path.extname(file)
      return validExtensions.includes(fileExtension)
    }
  })

  // 计算最长的文件名长度,以便在生成的 Markdown 中对齐文件描述
  let maxFileNameLength = 0
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    if (file.length > maxFileNameLength) {
      maxFileNameLength = file.length
    }
  }

  // 遍历每个文件和子目录,生成相应的 Markdown 行
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    const filePath = path.join(dir, file)
    const stats = fs.statSync(filePath)
    const tabs = `│   `.repeat(depth) // 制表符用于表示目录的深度

    if (stats.isDirectory()) {
      // 如果是目录,检查是否存在 README.md 文件,并读取其内容作为目录的注释
      let folderComment = ``
      let readmePath = ``
      if (fs.existsSync(path.join(filePath, `README.md`))) {
        const readmeContent = fs.readFileSync(path.join(filePath, `README.md`), `utf-8`)
        folderComment = readmeContent.split(`\n`)[0] ? `**${readmeContent.split(`\n`)[0]}**` : ``
        readmePath = `(/${path.join(filePath, `README.md`).replace(/\\/g, `/`)})`
      }
      const subdirContent = generateMarkdownStructure(filePath, depth + 1)
      if (subdirContent || readmePath) {
        result += `${tabs}├── [${file}/]${readmePath}    ${folderComment}\n`
        result += subdirContent
      }
    } else {
      // 如果是文件,读取文件的 @Description 注释,并生成相应的 Markdown 行
      const linePrefix = i === files.length - 1 && !stats.isDirectory() ? `└──` : `├──`
      let fileComment = ``
      const fileContent = fs.readFileSync(filePath, `utf-8`)
      const regex =
        /\/\*(?:[^*]|[\r\n]|(?:\*+(?:[^*/]|[\r\n])))*@Description:\s*([^*]*)(?:\*\/)|<!--[^]*?@Description:\s*([^]*?)(?:-->)/s
      const match = fileContent.match(regex)
      if (match && (match[1] || match[2])) {
        fileComment = (match[1] || match[2]).trim()
      }
      const numSpaces = maxFileNameLength - file.length
      const spaces = ` `.repeat(numSpaces * 2)
      result += `${tabs}${linePrefix} [${file}](/${filePath.replace(/\\/g, `/`)})    ${spaces}${fileComment}\n`
    }
  }
  return result
}

// 定义一个数组,列出需要生成 Markdown 文档的源目录和目标 Markdown 文件的路径
const mapArr = [
  { sourcePath: `./src/assets`, mdPath: `./doc/src/assets.md` },
  { sourcePath: `./src/components`, mdPath: `./doc/src/components.md` },
  { sourcePath: `./src/config`, mdPath: `./doc/src/config.md` },
  { sourcePath: `./src/hooks`, mdPath: `./doc/src/hooks.md` },
  { sourcePath: `./src/layout`, mdPath: `./doc/src/layout.md` },
  { sourcePath: `./src/plugins`, mdPath: `./doc/src/plugins.md` },
  { sourcePath: `./src/router`, mdPath: `./doc/src/router.md` },
  { sourcePath: `./src/services`, mdPath: `./doc/src/services.md` },
  { sourcePath: `./src/store`, mdPath: `./doc/src/store.md` },
  { sourcePath: `./src/utils`, mdPath: `./doc/src/utils.md` },
  { sourcePath: `./src/views`, mdPath: `./doc/src/views.md` },
  { sourcePath: `./src/views/dataAnalysis`, mdPath: `./doc/src/views/数据分析.md` },
  { sourcePath: `./src/views/dataExtract`, mdPath: `./doc/src/views/数据采集.md` },
  { sourcePath: `./src/views/dataGovernance`, mdPath: `./doc/src/views/数据治理.md` },
  { sourcePath: `./src/views/dataPreview`, mdPath: `./doc/src/views/数据预览.md` },
  { sourcePath: `./src/views/manage`, mdPath: `./doc/src/views/管理模块.md` },
  { sourcePath: `./src/views/metaDataManage`, mdPath: `./doc/src/views/元数据管理.md` },
  { sourcePath: `./src/views/other`, mdPath: `./doc/src/views/其他.md` },
]

// 遍历 mapArr 数组,为每个源目录调用 generateMarkdownStructure 函数,并将结果写入到对应的 Markdown 文件
mapArr.forEach(item => {
  const markdown = generateMarkdownStructure(item.sourcePath)
  fs.writeFileSync(item.mdPath, markdown)
})

主要功能

  1. 筛选有效文件:代码中定义了一个 validExtensions 数组,用于筛选出需要在 Markdown 中列出的文件类型。
  2. 读取文件描述:对于每个文件,代码会尝试读取文件内容中的 @Description 注释,以提供文件的简短描述。
  3. 递归处理目录:代码会递归地处理每个子目录,并为每个目录生成相应的结构。
  4. 生成 Markdown 链接:为每个文件和目录生成一个链接,使得在查看生成的 Markdown 文档时,可以直接点击链接访问对应的文件或目录。
  5. 处理多个目录:代码中定义了一个 mapArr 数组,列出了多个需要生成 Markdown 文档的源目录和目标 Markdown 文件的路径。代码会遍历这个数组,并为每个源目录生成一个 Markdown 文件。

代码流程

  1. 初始化:首先,代码导入了 fspath 模块,用于文件操作和路径处理。

  2. 定义有效的文件扩展名:定义了一个 validExtensions 数组,列出了需要在 Markdown 中显示的文件类型。

  3. 定义主函数 generateMarkdownStructure

    :这是一个递归函数,用于生成指定目录的 Markdown 结构。

    • 读取目录中的文件和子目录。
    • 筛选出有效的文件和子目录。
    • 计算最长的文件名长度,以便在生成的 Markdown 中对齐文件描述。
    • 遍历每个文件和子目录,生成相应的 Markdown 行。
    • 如果是目录,则递归调用 generateMarkdownStructure 函数。
    • 如果是文件,则读取文件的 @Description 注释,并生成相应的 Markdown 行。
  4. 处理多个目录:代码遍历 mapArr 数组,为每个源目录调用 generateMarkdownStructure 函数,并将结果写入到对应的 Markdown 文件。

转载自:https://juejin.cn/post/7281437377511260218
评论
请登录