项目中无用export的检测方案

背景

export是js中用于导出模块的关键字,用法如export const dataexport function getData等,在项目版本迭代过程中,开发人员会出现把引用处代码给删了,但是忘记删除export const的情况。

如下图,export const没删的话,打包会把代码打进去增加代码体积。

本文提供一种方案,可以快速检测项目中无用export的情况,开发人员可以根据实际考量进行清除。

export导出的检测

js 复制代码
const { parse, Lang } = require('@ast-grep/napi')
const fg = require('fast-glob')
const path = require('node:path')
const fs = require('node:fs')

const files = fg.sync([path.join(__dirname, '/src/**/*.js')])

const data = []
const addData = (node) => {
  const keyword = node?.getMatch?.('A')?.text?.() || ''
  if (keyword) {
    data.push(keyword)
  }
}
files.forEach((file) => {
  const source = fs.readFileSync(file, 'utf-8')
  const ast = parse(Lang.JavaScript, source)
  const root = ast.root()
  let node = root.find('export const $A = $B')
  addData(node)
  node = root.find('export function $A ($B) { $C }')
  addData(node)
  node = root.find('export let $A = $B')
  addData(node)
})

fs.writeFileSync('./data.json', JSON.stringify(data, null, 2))

上述代码很简单,执行流程就是用fast-glob把所有js文件扫出来,然后借助ast-grep,把所有的export const代码找出来。

无用export的识别

第一步我们是把所有的export const都找出来了,第二步我们需要从中识别出来哪些是有用的,哪些是无用的。从性能、执行速度考虑,我们采用golang实现本步骤,而不用js。

go 复制代码
package main

import (
  "encoding/json"
  "fmt"
  "os"
  "path/filepath"
  "strings"
  "sync"
)

// 结构用于存储计数结果
type StringCount struct {
  String string
  Count  int
}

func main() {
  // 1. 读取 json 文件
  jsonData, err := os.ReadFile("data.json")
  if err != nil {
    fmt.Printf("无法读取json: %v\n", err)
    return
  }

  // 2. 解析 JSON 数据
  var data []string
  if err := json.Unmarshal(jsonData, &data); err != nil {
    fmt.Printf("解析 JSON 失败: %v\n", err)
    return
  }

  // 3. 存储结果的映射
  resultMap := make(map[string]int)
  var mutex sync.Mutex
  var wg sync.WaitGroup

  // 4. 遍历指定目录中的文件
  searchDir := "./src"
  fileCount := 0
  isJsVue := func(filePath string) bool {
    return strings.HasSuffix(filePath, ".js") || strings.HasSuffix(filePath, ".vue")
  }

  // 5. 文件处理函数
  processFile := func(filePath string) {
    defer wg.Done()
    
    if !isJsVue(filePath) {
      return
    }
    content, err := os.ReadFile(filePath)
    if err != nil {
      return
    }    
    contentStr := string(content)
        
    // 检查每个字符串在文件中的出现次数
    for _, searchStr := range data {
      count := strings.Count(contentStr, searchStr)
      if count > 0 {
        mutex.Lock()
        resultMap[searchStr] += count
        mutex.Unlock()
      }
    }
  }

  err = filepath.Walk(searchDir, func(path string, info os.FileInfo, err error) error {
    if err != nil {
      return err
    }   
    // 跳过目录
    if info.IsDir() {
      return nil
    }
    if isJsVue(path) {
      fileCount++
      wg.Add(1)
      go processFile(path)
    }
    return nil
  })

  if err != nil {
    fmt.Printf("目录遍历错误: %v\n", err)
    return
  }

  // 等待所有文件处理完成
  wg.Wait()

  results := make([]StringCount, 0, len(resultMap))
  for str, count := range resultMap {
    if count == 1 {
      results = append(results, StringCount{String: str, Count: count})
    }
  }
  // 输出结果
  for _, result := range results {
    fmt.Printf("%s: %d次\n", result.String, result.Count)
  }
}

不会golang也没关系,交给ai生成golang代码就行,上面的go代码其实我也是用ai生成的,哈哈哈。我们不必过于担忧ai会替代我们,而是拥抱ai,有ai这个强大的辅助,开发人员所要做的就是在开发过程中思考、挖掘可提升改进的点,需要自身深入业务深入项目,深入之后发挥自己的创新力。

相关推荐
阿阳微客1 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏
德育处主任Pro1 小时前
『React』Fragment的用法及简写形式
前端·javascript·react.js
CodeBlossom2 小时前
javaweb -html -CSS
前端·javascript·html
打小就很皮...2 小时前
HBuilder 发行Android(apk包)全流程指南
前端·javascript·微信小程序
集成显卡3 小时前
PlayWright | 初识微软出品的 WEB 应用自动化测试框架
前端·chrome·测试工具·microsoft·自动化·edge浏览器
前端小趴菜054 小时前
React - 组件通信
前端·react.js·前端框架
Amy_cx4 小时前
在表单输入框按回车页面刷新的问题
前端·elementui
dancing9995 小时前
cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能
前端·javascript·typescript·游戏程序
后海 0_o5 小时前
2025前端微服务 - 无界 的实战应用
前端·微服务·架构
Scabbards_5 小时前
CPT304-2425-S2-Software Engineering II
前端