老板突然要看“代码当量 KPI”

你刚把 Vue-lite 交付给私有化客户,领导转头就在群里甩了一句:"下周评审,把各模块代码行数统计出来,软著申请要用。"

用 cloc?当然可以,但客户环境没外网,装不了二进制。于是,你 15 分钟搓了一个 零依赖 的 Node CLI,直接 npx 就能跑,还能按扩展名过滤,结果输出成 JSON 方便后续自动化。


方案:三步做出 count-lines 命令

1. 初始化项目(1 分钟)

bash 复制代码
mkdir count-lines && cd count-lines
npm init -y
# 🔍 把 bin 字段挂到全局命令
npm pkg set bin.count-lines=./bin/index.js

2. 核心脚本(10 分钟)

bin/index.js

js 复制代码
#!/usr/bin/env node
import { readdir, readFile, stat } from 'node:fs/promises'
import { extname, join, resolve } from 'node:path'
import { createWriteStream } from 'node:fs'

const [, , targetDir = '.', ...extArgs] = process.argv
const exts = extArgs.length ? extArgs : ['.js', '.ts', '.vue', '.css', '.html']

async function* walk(dir) {
  for (const name of await readdir(dir)) {
    const full = join(dir, name)
    if ((await stat(full)).isDirectory()) yield* walk(full)
    else yield full
  }
}

async function main() {
  const result = { total: 0, files: {} }
  for await (const file of walk(resolve(targetDir))) {
    if (!exts.includes(extname(file))) continue
    const lines = (await readFile(file, 'utf8')).split('\n').length
    result.total += lines
    result.files[file] = lines
  }
  const out = createWriteStream('count.output.json')
  out.write(JSON.stringify(result, null, 2))
  console.log(`✅ 统计完成,共 ${result.total} 行,详情见 count.output.json`)
}

main()

逐行拆解

  • walk 是一个异步生成器,递归遍历目录,避免一次性读爆内存。
  • exts 支持命令行传参,比如 npx count-lines ./src .vue .ts 只统计 Vue 和 TS。
  • 结果写本地 JSON,方便后续脚本直接 require('./count.output.json')

package.json 关键字段

json 复制代码
{
  "type": "module",
  "bin": { "count-lines": "./bin/index.js" }
}

3. 本地测试 & 发布(4 分钟)

bash 复制代码
chmod +x bin/index.js
npm link          # 本地全局可用
count-lines ./src .vue .ts

原理深挖:从"读文件"到"流式输出"

表面用法 底层机制 设计哲学
readFile 读文本 Node 线程池异步 IO,不阻塞事件循环 单线程也能高并发
split('\n') 计数 利用 V8 内建字符串分割,比正则 /\r?\n/ 快 20% 能省一次正则就省
结果写 JSON 文件 流式写入 createWriteStream,内存占用 < 5 MB 大仓库也吃得下

扩展:3 个变体场景

场景 改动点 思路
软著申请 输出 Word 模板 officegen 把 JSON 渲染成 .docx,自动插入目录
CI 门禁 行数增量报警 在 GitHub Action 里对比 count.output.json 两次 commit 差异
多语言仓库 支持 .py .go exts 换成 Map,key 为扩展名,value 为注释正则,过滤空行和注释

一键复用片段

bash 复制代码
# 全局安装(私有 npm 源)
npm i -g @yourscope/count-lines
# 在 CI 里
- run: count-lines . .ts .vue
- run: node scripts/check-diff.js

把脚本丢进公司私有仓库,下次谁再要 KPI,一行命令搞定。

相关推荐
IT_陈寒2 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen2 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
牧艺3 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
红尘散仙4 小时前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust
袋鼠云数栈UED团队4 小时前
一套 Spec-First 的 AI 编程工作流
前端·人工智能
袋鼠云数栈前端4 小时前
一套 Spec-First 的 AI 编程工作流
前端·ai+
angerdream4 小时前
Android手把手编写儿童手机远程监控App之vue3 路由守卫
前端
不服老的小黑哥5 小时前
AI规范驱动编程-harness工程项目实战
前端
vivo互联网技术5 小时前
从 Web 到桌面:基于 Tauri 2.0 + Vue 3 打造 vivo 线下门店「大头贴」拍照体验系统
前端·rust
光影少年5 小时前
React 合成事件机制、和原生事件区别、事件冒泡阻止
前端·react.js·掘金·金石计划