项目中无用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这个强大的辅助,开发人员所要做的就是在开发过程中思考、挖掘可提升改进的点,需要自身深入业务深入项目,深入之后发挥自己的创新力。

相关推荐
汤姆Tom6 分钟前
CSS 预处理器深入应用:提升开发效率的利器
前端·css·面试
练习前端两年半6 分钟前
Vue3组件二次封装终极指南:动态组件+h函数的优雅实现
前端·vue.js
皮皮虾我们跑15 分钟前
前端HTML常用基础标
前端·javascript·html
Yeats_Liao16 分钟前
Go Web 编程快速入门 01 - 环境准备与第一个 Web 应用
开发语言·前端·golang
卓码软件测评16 分钟前
第三方CMA软件测试机构:页面JavaScript动态渲染生成内容对网站SEO的影响
开发语言·前端·javascript·ecmascript
Mintopia19 分钟前
📚 Next.js 分页 & 模糊搜索:在无限数据海里优雅地翻页
前端·javascript·全栈
Mintopia20 分钟前
⚖️ AIGC版权确权技术:Web内容的AI生成标识与法律适配
前端·javascript·aigc
周家大小姐.31 分钟前
vue实现模拟deepseekAI功能
前端·javascript·vue.js
小张成长计划..1 小时前
前端7:综合案例--品优购项目(HTML+CSS)
前端·css·html
一个处女座的程序猿O(∩_∩)O1 小时前
React 多组件状态管理:从组件状态到全局状态管理全面指南
前端·react.js·前端框架