你刚把 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,一行命令搞定。