服务端阅读 06月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 重新安装。不一定要全局安装,临时使用可以这样跑:npx npm-check-updatesnpx npm-check-updates -unpm install常见用法:# 只看生产依赖npx npm-check-updates --dep prod# 只更新 patch,适合保守升级npx npm-check-updates -u --target patch# 只更新 minornpx npm-check-updates -u --target minor# 使用指定 registrynpx npm-check-updates --registry https://registry.npmmirror.com它适合做“依赖升级前的体检”。如果项目稳定性要求高,不建议直接 ncu -u 后一把安装,最好先升级 patch/minor,再单独评估 major 版本。npm-check:交互式查看依赖状态npm-check 更适合人工巡检。它会把依赖更新、未使用依赖、缺失依赖等信息放在交互界面里,适合本地排查,不太适合放进 CI 阻塞流程。npx npm-checknpx npm-check -unpx npm-check --ignore-unused如果团队已经有 Renovate、Dependabot 之类的自动升级工具,npm-check 的价值会下降,但它仍然适合在大版本升级前快速扫一遍项目状态。depcheck:找出未使用和缺失依赖depcheck 用来检查两类问题:package.json 里写了,但代码里可能没用到的包;代码里引用了,但 package.json 里可能没声明的包。npx depchecknpx depcheck ./srcnpx depcheck --ignore-patterns=dist,coverage它的结果需要人工判断。比如 Babel、ESLint、Vite、Webpack 插件可能只出现在配置文件里,动态 import、约定式插件也可能被误判。比较稳妥的做法是:先用它生成候选清单,再结合构建、测试和运行结果删除依赖。安全审计:npm audit 负责底线,Snyk 补充风险视角npm audit:内置漏洞扫描npm audit 是 npm 自带的安全检查,适合每个项目默认开启。npm auditnpm audit --audit-level=highnpm audit fix --dry-runnpm audit fixnpm audit fix --force 要谨慎,它可能引入破坏性升级。生产项目更推荐先看 --dry-run 结果,再决定是否手动升级关键包。如果只关注生产依赖,新版 npm 更推荐使用:npm audit --omit=devnpm audit fix --omit=devSnyk:适合需要持续监控的项目Snyk 的优势是漏洞库、修复建议和项目监控更完整,适合团队项目、开源库和对安全要求较高的业务。npx snyk authnpx snyk testnpx snyk test --severity-threshold=highnpx snyk monitorGitHub Actions 里可以只阻塞高危漏洞:- name: Snyk security check uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=highretire.js:更适合检查旧前端资源retire 主要用于识别 JavaScript 库的已知漏洞,尤其是老项目里直接放在 public、vendor、static 目录下的前端库。npx retire --path ./publicnpx retire --path ./dist --outputformat json如果项目完全通过 npm 管理依赖,优先级通常是 npm audit 和 Snyk;如果项目里还有手工复制的 jQuery、Bootstrap、旧插件文件,retire 就很有用。包体积和发布内容:别等用户下载完才发现问题npm-packlist 与 npm pack:确认发布包会包含什么发布 npm 包前,最怕两件事:源码漏了,或者测试文件、截图、临时文件被打进去了。可以先用 npm 自带命令检查:npm pack --dry-runnpm 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 会统计依赖安装后的体积和成本,适合用来发现“一个小功能带来一大包依赖”的情况。npx cost-of-modulesnpx cost-of-modules --json它不必每次 CI 都跑,更适合在项目依赖明显膨胀、安装变慢、容器镜像变大时做分析。脚本编排:npm-run-all 和 concurrently 分工不同npm-run-all:适合组合 npm scriptsnpm-run-all 解决的是“多个脚本按顺序或并行执行”的问题。npm install -D npm-run-all{ "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" }}常用命令:run-s clean build testrun-p lint testrun-s clean "run-p lint test" buildrun-s 表示顺序执行,run-p 表示并行执行。它更适合一次性任务,比如构建、测试、发布前检查。concurrently:适合同时启动长期进程concurrently 更适合开发环境,比如同时启动前端、后端和测试监听。npm install -D concurrently{ "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\"" }}常用参数: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 文档。npm install -D jsdocnpx jsdoc src -d docsnpx jsdoc -c jsdoc.conf.json如果项目已经大量使用 TypeScript,JSDoc 的重点可以放在“说明行为和边界”,不要把类型信息重复写一遍。documentation:适合生成 Markdown 或 HTML 文档documentation 更适合把 API 文档输出成 Markdown、HTML 或 JSON,方便放进站点或 README。npm install -D documentationnpx documentation build src -f html -o docsnpx documentation build src -f md -o API.mdnpx documentation build src -f json -o api.json对开源库来说,文档工具的价值不只是生成页面,而是逼你确认公共 API 是否稳定、参数是否清楚、异常行为是否写明。nyc:统计测试覆盖率nyc 是 Istanbul 的命令行工具,适合 Mocha、AVA 等测试框架,也能配合很多 Node.js 测试命令使用。npm install -D nycnpx nyc npm testnpx nyc report --reporter=htmlnpx nyc --check-coverage --lines 80 npm test覆盖率阈值不要一开始就设得很高。老项目可以先记录基线,再逐步提高;新项目可以对核心目录设置更严格的要求。testdouble:让单元测试少依赖外部环境testdouble 用来创建测试替身,适合隔离网络请求、文件系统、数据库访问等外部依赖。npm install -D testdoubleconst 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 定制较多的项目。npm install -D webpack webpack-clinpx webpack --config webpack.config.jsnpx webpack --mode productionnpx webpack --watch如果项目是大型 Web 应用,且已有复杂配置,继续使用 webpack 很正常;如果是新项目,也可以结合 Vite 等工具评估启动速度和配置成本。rollup:适合库和组件包Rollup 更适合打包库,尤其是希望输出 ESM、CJS、UMD 多种格式,并保持较好 tree-shaking 的项目。npm install -D rollupnpx rollup -cnpx rollup -c -w常见选择是:应用用 webpack/Vite,库用 rollup/tsup。工具不是越统一越好,关键是产物形态和维护成本合适。nodemon:Node 服务开发时自动重启nodemon 会监听文件变化并重启 Node.js 进程,适合 API 服务、本地脚本、CLI 开发。npm install -D nodemon{ "scripts": { "dev": "nodemon app.js", "dev:debug": "nodemon --inspect app.js", "dev:watch": "nodemon --watch src app.js" }}live-server:简单静态页面预览live-server 适合预览静态 HTML、构建后的 demo 或文档站点,不适合复杂前端应用的正式开发服务器。npx live-servernpx live-server --port=8080npx live-server --root=distnpx live-server --ignore=node_modules如果只是临时看一个 dist 目录,它很方便;如果项目已经用 Vite、Next.js、Nuxt 或自带 dev server,就没必要再加一层。发布自动化:np 适合人工确认,semantic-release 适合机器发布np:让手动发布更稳np 会帮你做发布前检查,比如工作区是否干净、测试是否通过、版本号和 tag 是否正确。它适合仍然希望人工确认版本和发布动作的 npm 包。npm install -D npnpx npnpx np 1.2.3npx np --tag betanp --yolo 会跳过不少检查,除非是临时包或内部包,否则不建议作为常规流程。semantic-release:根据提交记录自动发版semantic-release 适合成熟团队和持续发布场景。它通常依赖 Conventional Commits,根据 commit 类型自动判断版本、生成 release notes,并发布到 npm 或 GitHub。npm install -D semantic-release @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm @semantic-release/github.releaserc.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 hooksHusky 用来把检查命令挂到 Git hooks 上,例如提交前跑 lint、提交信息校验等。现代版本通常这样初始化:npm install -D huskynpx husky init然后编辑 .husky/pre-commit:npm test或者只跑更快的检查,避免每次提交都等很久。lint-staged:只检查暂存文件lint-staged 的价值是“只处理这次提交涉及的文件”,比全量 lint 更快。npm install -D lint-staged{ "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 或前端项目,不追求工具最多,只覆盖日常维护的关键点:{ "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、Snyk | npm 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 工具,不是清单最长的那组,而是大家每天都愿意运行、出了问题也知道该怎么修的那组。