6月19日 12:17

npm 工具有哪些?如何按项目场景选择?

npm 生态里的工具很多,但项目里真正值得长期保留的,通常只解决几类问题:依赖更新、依赖清理、安全扫描、包体积控制、脚本编排、文档测试、构建开发、发布和 Git 工作流。

选工具时不要先问“有哪些”,而要先问“现在项目最卡在哪里”。依赖老旧就看 npm-check-updates;怀疑装了没用的包就跑 depcheck;发布前担心漏文件就检查 packlist;团队提交质量不稳定,再加 husky 和 lint-staged。

依赖更新:先看影响范围,再决定升不升

npm-check-updates:批量检查 package.json 版本

npm-check-updates 常用来检查 package.json 里的依赖是否有新版本。它不会直接安装依赖,通常先改版本声明,再由 npm、pnpm 或 yarn 重新安装。

不一定要全局安装,临时使用可以这样跑:

bash
npx npm-check-updates npx npm-check-updates -u npm install

常见用法:

bash
# 只看生产依赖 npx npm-check-updates --dep prod # 只更新 patch,适合保守升级 npx npm-check-updates -u --target patch # 只更新 minor npx npm-check-updates -u --target minor # 使用指定 registry npx npm-check-updates --registry https://registry.npmmirror.com

它适合做“依赖升级前的体检”。如果项目稳定性要求高,不建议直接 ncu -u 后一把安装,最好先升级 patch/minor,再单独评估 major 版本。

npm-check:交互式查看依赖状态

npm-check 更适合人工巡检。它会把依赖更新、未使用依赖、缺失依赖等信息放在交互界面里,适合本地排查,不太适合放进 CI 阻塞流程。

bash
npx npm-check npx npm-check -u npx npm-check --ignore-unused

如果团队已经有 Renovate、Dependabot 之类的自动升级工具,npm-check 的价值会下降,但它仍然适合在大版本升级前快速扫一遍项目状态。

depcheck:找出未使用和缺失依赖

depcheck 用来检查两类问题:

  • package.json 里写了,但代码里可能没用到的包;
  • 代码里引用了,但 package.json 里可能没声明的包。
bash
npx depcheck npx depcheck ./src npx depcheck --ignore-patterns=dist,coverage

它的结果需要人工判断。比如 Babel、ESLint、Vite、Webpack 插件可能只出现在配置文件里,动态 import、约定式插件也可能被误判。比较稳妥的做法是:先用它生成候选清单,再结合构建、测试和运行结果删除依赖。

安全审计:npm audit 负责底线,Snyk 补充风险视角

npm audit:内置漏洞扫描

npm audit 是 npm 自带的安全检查,适合每个项目默认开启。

bash
npm audit npm audit --audit-level=high npm audit fix --dry-run npm audit fix

npm audit fix --force 要谨慎,它可能引入破坏性升级。生产项目更推荐先看 --dry-run 结果,再决定是否手动升级关键包。

如果只关注生产依赖,新版 npm 更推荐使用:

bash
npm audit --omit=dev npm audit fix --omit=dev

Snyk:适合需要持续监控的项目

Snyk 的优势是漏洞库、修复建议和项目监控更完整,适合团队项目、开源库和对安全要求较高的业务。

bash
npx snyk auth npx snyk test npx snyk test --severity-threshold=high npx snyk monitor

GitHub Actions 里可以只阻塞高危漏洞:

yaml
- name: Snyk security check uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high

retire.js:更适合检查旧前端资源

retire 主要用于识别 JavaScript 库的已知漏洞,尤其是老项目里直接放在 publicvendorstatic 目录下的前端库。

bash
npx retire --path ./public npx retire --path ./dist --outputformat json

如果项目完全通过 npm 管理依赖,优先级通常是 npm audit 和 Snyk;如果项目里还有手工复制的 jQuery、Bootstrap、旧插件文件,retire 就很有用。

包体积和发布内容:别等用户下载完才发现问题

npm-packlist 与 npm pack:确认发布包会包含什么

发布 npm 包前,最怕两件事:源码漏了,或者测试文件、截图、临时文件被打进去了。

可以先用 npm 自带命令检查:

bash
npm pack --dry-run npm pack --dry-run --json

如果需要和 npm 实际打包规则保持一致,可以使用 npm-packlist 做更细的检查。它会参考 files.npmignore.gitignore 等规则,判断哪些文件会进入最终包。

发布库时建议重点看:

  • dist 或构建产物是否存在;
  • 类型声明文件是否被包含;
  • README、LICENSE 是否存在;
  • 测试数据、私有配置、临时日志是否误入包内。

bundlephobia:评估依赖对前端包体积的影响

Bundlephobia 适合在新增依赖前看一眼包大小,尤其是浏览器端项目。

可以直接访问 Bundlephobia 网站搜索包名,也可以把它当成评审习惯:新增一个工具库前,先看它的 minified、gzipped 体积,以及是否会带来一串间接依赖。

典型场景:

  • 为一个小函数引入大型工具库;
  • 日期处理库替换;
  • 图表、富文本、拖拽库选型;
  • SDK 是否应该按需加载。

cost-of-modules:看依赖安装成本

cost-of-modules 会统计依赖安装后的体积和成本,适合用来发现“一个小功能带来一大包依赖”的情况。

bash
npx cost-of-modules npx cost-of-modules --json

它不必每次 CI 都跑,更适合在项目依赖明显膨胀、安装变慢、容器镜像变大时做分析。

脚本编排:npm-run-all 和 concurrently 分工不同

npm-run-all:适合组合 npm scripts

npm-run-all 解决的是“多个脚本按顺序或并行执行”的问题。

bash
npm install -D npm-run-all
json
{ "scripts": { "clean": "rimraf dist", "lint": "eslint src", "test": "vitest run", "build": "webpack --mode production", "check": "run-p lint test", "release:build": "run-s clean check build" } }

常用命令:

bash
run-s clean build test run-p lint test run-s clean "run-p lint test" build

run-s 表示顺序执行,run-p 表示并行执行。它更适合一次性任务,比如构建、测试、发布前检查。

concurrently:适合同时启动长期进程

concurrently 更适合开发环境,比如同时启动前端、后端和测试监听。

bash
npm install -D concurrently
json
{ "scripts": { "dev:api": "nodemon server.js", "dev:web": "vite", "dev": "concurrently --names API,WEB --prefix-colors blue,green \"npm run dev:api\" \"npm run dev:web\"" } }

常用参数:

bash
concurrently "npm run dev" "npm run test:watch" concurrently --kill-others "npm run api" "npm run web" concurrently --names "API,WEB" "npm run api" "npm run web"

简单判断:短任务编排用 npm-run-all,长期进程并跑用 concurrently

文档和测试:先覆盖公共 API,再追求漂亮页面

jsdoc:适合从注释生成 API 文档

jsdoc 适合传统 JavaScript 项目,也适合给公共函数、类、模块生成 API 文档。

bash
npm install -D jsdoc npx jsdoc src -d docs npx jsdoc -c jsdoc.conf.json

如果项目已经大量使用 TypeScript,JSDoc 的重点可以放在“说明行为和边界”,不要把类型信息重复写一遍。

documentation:适合生成 Markdown 或 HTML 文档

documentation 更适合把 API 文档输出成 Markdown、HTML 或 JSON,方便放进站点或 README。

bash
npm install -D documentation npx documentation build src -f html -o docs npx documentation build src -f md -o API.md npx documentation build src -f json -o api.json

对开源库来说,文档工具的价值不只是生成页面,而是逼你确认公共 API 是否稳定、参数是否清楚、异常行为是否写明。

nyc:统计测试覆盖率

nyc 是 Istanbul 的命令行工具,适合 Mocha、AVA 等测试框架,也能配合很多 Node.js 测试命令使用。

bash
npm install -D nyc npx nyc npm test npx nyc report --reporter=html npx nyc --check-coverage --lines 80 npm test

覆盖率阈值不要一开始就设得很高。老项目可以先记录基线,再逐步提高;新项目可以对核心目录设置更严格的要求。

testdouble:让单元测试少依赖外部环境

testdouble 用来创建测试替身,适合隔离网络请求、文件系统、数据库访问等外部依赖。

bash
npm install -D testdouble
js
const td = require('testdouble') const send = td.function('send') send('hello') td.verify(send('hello'))

如果项目已经使用 Jest 或 Vitest 自带 mock,未必需要再引入 testdouble;但在偏函数式、模块边界清晰的 Node.js 项目里,它的表达会比较直接。

构建和开发:webpack、rollup、nodemon、live-server 各有位置

webpack:适合应用型项目

Webpack 的优势是生态成熟,处理复杂前端应用很稳,尤其是多类型资源、代码分割、Loader/Plugin 定制较多的项目。

bash
npm install -D webpack webpack-cli npx webpack --config webpack.config.js npx webpack --mode production npx webpack --watch

如果项目是大型 Web 应用,且已有复杂配置,继续使用 webpack 很正常;如果是新项目,也可以结合 Vite 等工具评估启动速度和配置成本。

rollup:适合库和组件包

Rollup 更适合打包库,尤其是希望输出 ESM、CJS、UMD 多种格式,并保持较好 tree-shaking 的项目。

bash
npm install -D rollup npx rollup -c npx rollup -c -w

常见选择是:应用用 webpack/Vite,库用 rollup/tsup。工具不是越统一越好,关键是产物形态和维护成本合适。

nodemon:Node 服务开发时自动重启

nodemon 会监听文件变化并重启 Node.js 进程,适合 API 服务、本地脚本、CLI 开发。

bash
npm install -D nodemon
json
{ "scripts": { "dev": "nodemon app.js", "dev:debug": "nodemon --inspect app.js", "dev:watch": "nodemon --watch src app.js" } }

live-server:简单静态页面预览

live-server 适合预览静态 HTML、构建后的 demo 或文档站点,不适合复杂前端应用的正式开发服务器。

bash
npx live-server npx live-server --port=8080 npx live-server --root=dist npx live-server --ignore=node_modules

如果只是临时看一个 dist 目录,它很方便;如果项目已经用 Vite、Next.js、Nuxt 或自带 dev server,就没必要再加一层。

发布自动化:np 适合人工确认,semantic-release 适合机器发布

np:让手动发布更稳

np 会帮你做发布前检查,比如工作区是否干净、测试是否通过、版本号和 tag 是否正确。它适合仍然希望人工确认版本和发布动作的 npm 包。

bash
npm install -D np npx np npx np 1.2.3 npx np --tag beta

np --yolo 会跳过不少检查,除非是临时包或内部包,否则不建议作为常规流程。

semantic-release:根据提交记录自动发版

semantic-release 适合成熟团队和持续发布场景。它通常依赖 Conventional Commits,根据 commit 类型自动判断版本、生成 release notes,并发布到 npm 或 GitHub。

bash
npm install -D semantic-release @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm @semantic-release/github

.releaserc.json 示例:

json
{ "branches": ["main"], "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/npm", "@semantic-release/github" ] }

如果团队提交信息不规范,先上 semantic-release 反而会痛苦。可以先用 commitlint 和 husky 把提交格式稳定下来。

Git 工作流:husky 和 lint-staged 管住提交入口

husky:管理 Git hooks

Husky 用来把检查命令挂到 Git hooks 上,例如提交前跑 lint、提交信息校验等。

现代版本通常这样初始化:

bash
npm install -D husky npx husky init

然后编辑 .husky/pre-commit

bash
npm test

或者只跑更快的检查,避免每次提交都等很久。

lint-staged:只检查暂存文件

lint-staged 的价值是“只处理这次提交涉及的文件”,比全量 lint 更快。

bash
npm install -D lint-staged
json
{ "lint-staged": { "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"], "*.{css,scss,md,json}": ["prettier --write"] } }

新版 lint-staged 会处理修改后的文件状态,通常不需要再手写 git add。如果团队成员经常因为 hook 太慢而绕过检查,说明 hook 里放的任务太重了,应该把耗时任务挪到 CI。

一个比较实用的 package.json 组合

下面这个组合适合中小型 Node.js 或前端项目,不追求工具最多,只覆盖日常维护的关键点:

json
{ "scripts": { "dev": "concurrently --names API,WEB \"npm run dev:api\" \"npm run dev:web\"", "dev:api": "nodemon server.js", "dev:web": "vite", "lint": "eslint src", "test": "vitest run", "test:coverage": "nyc npm test", "check": "run-p lint test", "deps:check": "npm-check", "deps:update": "ncu -u", "deps:unused": "depcheck", "security": "npm audit --audit-level=high", "pack:check": "npm pack --dry-run", "build": "webpack --mode production", "release": "np" }, "lint-staged": { "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"] } }

这类脚本的好处是团队不用记住每个工具的参数,只要记住几个入口:

  • npm run check:提交或合并前的基础检查;
  • npm run security:安全审计;
  • npm run deps:unused:依赖清理;
  • npm run pack:check:发布前确认文件;
  • npm run release:发布流程。

怎么决定工具要不要进项目

可以用几个很朴素的标准判断:

场景推荐工具是否建议进 devDependencies
经常检查依赖更新npm-check-updates、npm-check可以
偶尔清理依赖depcheck可以,也可 npx 临时跑
每次 CI 做安全检查npm audit、Snyknpm audit 内置,Snyk 看团队需求
发布 npm 包npm pack、npm-packlist、np建议
控制前端体积bundlephobia、cost-of-modules多数情况下临时使用即可
多脚本编排npm-run-all、concurrently建议
生成 API 文档jsdoc、documentation看项目是否对外提供 API
覆盖率统计nyc建议用于库或核心服务
自动重启服务nodemon建议用于 Node 服务
提交前检查husky、lint-staged团队项目建议

最后要注意一点:工具本身也会增加维护成本。能用 npm 内置能力解决的,就别急着加依赖;需要团队统一入口的,再把它写进 scripts。一个项目里真正有价值的 npm 工具,不是清单最长的那组,而是大家每天都愿意运行、出了问题也知道该怎么修的那组。

标签:NPM