发布于 2025 年 10 月 26 日,星期日
我用Knip清理了Nx项目,一口气删了120个没用的依赖
Knip扫描Nx Monorepo,自动识别未引用依赖、冗余文件与空入口,一键移除120个包并同步更新tsconfig、项目引用与IDE索引;对比手动清理流程,展示扫描规则、白名单配置与CI集成技巧,显著缩减安装、构建耗时并降低漏洞面,为大型工程提供可复制的依赖瘦身方案。
如何使用 Knip 来清理项目依赖包?
yarn install 的时间直接快了一分钟,那些烦人的安全警告也少了一大堆。
为啥要清理
现在仓库有点臃肿了,大概 500 个依赖散落在各个应用和包里,不全在根目录。
装依赖慢,安全警告多,看着就烦。想清理一下,但又不能搞坏东西。
为什么用 Knip
之前我用 depcheck 比较多,但这工具好几年没更新了,对新的项目结构支持不太好。
后来看到 Knip,专门为单体仓库设计的,而且还在持续更新。depcheck 官方现在也推荐它了。
Knip 会从入口文件开始,构建一个导入关系图,然后和 package.json 对比,找出那些没被用到的包。
虽然不是百分百准确,但作为第一步筛选够用了。
具体怎么操作的
先跑一遍扫描:
yarn dlx knip
然后跑测试,看看哪些地方会炸:
yarn nx affected -t build test lint
# 本地也启动一下应用
yarn nx run <app>:serve
第一次扫描 Knip 会标记一堆东西,但大概 40% 都是误报,这很正常。
怎么判断能不能删
Knip 只是个参考,不能完全信它。
我对每个被标记的包都这么处理:
- 先卸载掉
- 跑构建、测试、lint、e2e,还有类型生成
- 再启动应用看看
- 如果出问题就装回来,记到忽略列表里
大多数误报都是这几种情况:
- 配置文件里用字符串引用的,比如 Jest 的 preset 名称
- 只在脚本或 CI 里用的命令行工具
- 插件自动发现机制用到的
- 只提供类型或构建工具链的包
我把这些都加到忽略列表里,顺便写个简单的注释,免得以后忘了。
Knip 配置
我针对单体仓库做了点调整,加了些常见的误报忽略:
/** @type {import('knip').KnipConfig} */
const config = {
include: ["dependencies", "devDependencies"],
ignoreWorkspaces: ["packages/eslint-config"],
ignoreDependencies: [
"ts-node", // jest 配置里用名字引用的
"cross-env", // 只在脚本里用
],
workspaces: {
"apps/cms": {
ignoreDependencies: ["@sanity/vision"],
},
"packages/ui": {
ignoreDependencies: [
"tw-animate-css", // global.css 里用 @import 引的
"@tailwindcss/typography", // 同上
],
},
},
};
export default config;
你的项目配置肯定不一样,这只是个参考。
验证流程
删掉一个包,构建,测试,跑一遍。
本地开发环境也跑起来看看有没有问题。
如果都是绿的,就提交。不行就装回来,加到忽略列表。
我还部署了个预览环境,点了几个常用功能,看控制台有没有报错。
没啥异常,这是最好的结果。
清理效果
之前大概 510 个包,清理后剩 390 个。删了 120 个左右。
yarn install 在我本地和 CI 上都快了一分钟。
Knip 哪些做得好哪些不行
它对常见的 React 和服务端应用入口点识别得挺准,各种配置约定也认识。
但对间接使用或者只在脚本、CI 里用的包就不太行了。
没关系,人工判断一下就好了。
怎么合并代码不影响别人
小 PR 更安全,但我这次打了个大包,部署到预览分支。
选了个安静的时间段合并,这样万一要回滚也只影响我这个 PR。
合并后我让它跑了一会儿,点了几个用户流程,看了看日志。
没出问题。
额外功能
Knip 还能找没用的文件、枚举、类型。
清理死代码的时候也挺好用,同样是作为参考,还得真正跑构建和测试验证。