news 2026/9/13 6:47:55

Backstage example-app Knip 依赖分析报告:knip-report.md 逐列解读与 build:knip-reports 生成机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Backstage example-app Knip 依赖分析报告:knip-report.md 逐列解读与 build:knip-reports 生成机制

Backstage example-app Knip 依赖分析报告:knip-report.md 逐列解读与 build:knip-reports 生成机制

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

本文以 Backstage 仓库中提交到版本库的 example-app Knip 依赖分析报告 为主体,完整解读其“未使用依赖”清单中每一列的含义与数据背景,并结合 repo-tools 报告生成实现 讲清报告的生成命令、临时配置、路径归一化与 CI 一致性校验机制,帮助你在改动前端包依赖时正确复现、维护并消费这份报告。

一、knip-report.md 是什么:提交到仓库的依赖健康基线

在 Backstage 这个 Yarn monorepo(根 package.json 声明了packages/*plugins/*两个 workspaces 通配目录)中,几乎每个工作区包目录下都有一份knip-report.md(例如 packages/app/knip-report.md、packages/app-defaults/knip-report.md)。它不是人工撰写的文档,而是由 Knip 依赖分析工具针对单个包生成的“未使用依赖”清单,并被作为基线文件提交进仓库:CI 会重新运行分析,只要实际结果与已提交的报告不一致就构建失败,从而保证依赖清单的任何漂移都必须在报告中显式体现。

本文主角 packages/app/knip-report.md 对应的是 packages/app/package.json 中定义的example-app前端应用包("backstage": { "role": "frontend" })。该报告当前记录了27 个未使用的 dependencies5 个未使用的 devDependencies

二、报告内容逐列解读

报告采用 Markdown 表格,共三列,含义如下:

  • Name:被 Knip 判定为未使用的依赖包名;
  • Location:该依赖声明在所属包package.json中的“行:列”位置(例如package.json:77:6指该行第 6 列,即键名起始处),与 packages/app/package.json 中的依赖条目一一对应;
  • Severity:Knip 对该发现的严重级别,本报告中全部为error

2.1 Unused dependencies(27 项)

原文档中该小节完整内容如下:

NameLocationSeverity
@backstage/plugin-techdocs-module-addons-contribpackage.json:77:6error
@backstage/plugin-catalog-unprocessed-entitiespackage.json:61:6error
@backstage/plugin-kubernetes-clusterpackage.json:66:6error
@backstage/plugin-permission-reactpackage.json:69:6error
@backstage/plugin-scaffolder-reactpackage.json:71:6error
@backstage/plugin-catalog-commonpackage.json:57:6error
@backstage/plugin-techdocs-reactpackage.json:78:6error
@backstage/plugin-catalog-graphpackage.json:58:6error
@backstage/plugin-search-commonpackage.json:73:6error
@backstage/plugin-search-reactpackage.json:74:6error
@backstage/integration-reactpackage.json:49:6error
@backstage/plugin-auth-reactpackage.json:55:6error
@backstage/plugin-scaffolderpackage.json:70:6error
@backstage/core-plugin-apipackage.json:45:6error
@backstage/plugin-api-docspackage.json:50:6error
@backstage/plugin-devtoolspackage.json:62:6error
@backstage/plugin-signalspackage.json:75:6error
@backstage/app-defaultspackage.json:38:6error
@backstage/plugin-authpackage.json:54:6error
@backstage/plugin-apppackage.json:51:6error
@backstage/plugin-orgpackage.json:68:6error
@backstage/configpackage.json:41:6error
@material-ui/labpackage.json:84:6error
zen-observablepackage.json:92:6error
@octokit/restpackage.json:85:6error
react-usepackage.json:91:6error
historypackage.json:86:6error

2.2 Unused devDependencies(5 项)

NameLocationSeverity
@testing-library/user-eventpackage.json:100:6error
@types/zen-observablepackage.json:104:6error
@types/jquerypackage.json:101:6error
cross-envpackage.json:105:6error
@testing-library/dompackage.json:97:6error

2.3 为什么这些依赖会被判定为“未使用”

理解这份清单的关键在于 Knip 的分析方式:它从入口文件出发做可达性追踪,只有能被入口代码(含其导入链)引用到的依赖才视为“在用”。Backstage 的生成器为{packages,plugins}/*统一配置了如下入口(见 knip-extractor.ts 中动态生成的配置):

  • 主入口:dev/**/*.{ts,tsx}src/index.{ts,tsx}
  • Jest 入口:src/setupTests.tssrc/**/*.test.{ts,tsx}
  • Storybook 入口:src/components/**/*.stories.tsx

对照 packages/app/package.json 可以观察到:example-app声明了 30 余个@backstage/*工作区依赖,但从源码结构看,其入口代码主要通过@backstage/app-defaults@backstage/frontend-defaults等聚合包间接消费大量子包,@backstage/core-plugin-api@backstage/plugin-org等并未在该包的入口导入链中被直接引用,因此被 Knip 列入未使用清单。需要强调的是,这份报告是仓库有意提交保留的基线:其中部分依赖可能服务于构建期、兼容性或未来接线场景,报告的作用是把“当前未被直接引用”这件事显式记录并纳入 CI 校验,而非要求立即删除它们。

另外值得注意的是报告没有“Unlisted dependencies” 一节。生成命令显式开启了--include dependencies,unlisted两项检查,即同时检测“已声明但未使用”与“已导入但未声明”的依赖;后者在当前快照中为空,所以只输出了上面两个小节。

三、报告如何生成:yarn build:knip-reports 全链路

3.1 入口脚本与命令用法

根 package.json 中注册了报告生成脚本:

"build:knip-reports": "backstage-repo-tools knip-reports"

repo-tools 的 CLI 报告 中记载了完整用法:

Usage: backstage-repo-tools knip-reports [options] [paths...] Options: --ci -h, --help

即不带参数时分析所有包,带参数时只分析指定包路径。命令入口实现 在“分析所有包且非 CI”时会额外打印一条提示,教你如何用包路径缩小范围:

yarn build:knip-reports packages/config packages/core-plugin-api plugins/*

3.2 动态生成 knip.json 配置

runKnipReports 执行时先在仓库根目录动态写入一份临时knip.json(分析完成后删除),其配置要点如下:

{ "workspaces": { ".": {}, "{packages,plugins}/*": { "entry": ["dev/**/*.{ts,tsx}", "src/index.{ts,tsx}"], "ignore": [ ".eslintrc.js", "config.d.ts", "knexfile.js", "node_modules/**", "dist/**", "{fixtures,migrations,templates}/**", "src/tests/transforms/__fixtures__/**" ] } }, "jest": { "entry": ["src/setupTests.ts", "src/**/*.test.{ts,tsx}"] }, "storybook": { "entry": "src/components/**/*.stories.tsx" }, "ignoreDependencies": [ "@types/react", "@types/jest", "@internal/.*", "@backstage/cli", "@backstage/theme" ] }

其中ignoreDependencies是理解“为什么某些看起来该报的包没报”的关键,源码中的注释给出了原因:

  • @types/react@types/jest:被报告为“被引用的可选 peerDependencies”,具体触发机制源码中留有 TBD 备注;
  • @internal/.*:内部包不发布且会被内联,无法按常规依赖解析;
  • @backstage/cli:所有包都依赖它执行package.json中声明的命令,属于构建期隐式依赖;
  • @backstage/theme:通过.d.ts中的declare module扩展模块声明,凡是需要模块扩展处即隐式使用,静态追踪无法感知。

ignore列表则排除配置文件、fixtures/migrations/templates等不参与可达性追踪的目录,避免它们误判依赖使用情况。

3.3 逐包执行 Knip 并归一化报告

对每个选中包,handlePackage 在仓库根目录执行如下命令(直接调用node_modules/knip/bin/knip.js):

node_modules/knip/bin/knip.js -W <包路径> \ --config knip.json \ --no-exit-code \ --no-progress \ --include dependencies,unlisted \ --reporter markdown

各参数的作用:

  • -W <包路径>:在 monorepo 中指定要分析的目标 workspace;
  • --config knip.json:使用上一步动态生成的临时配置;
  • --no-exit-code不因发现问题而使进程非零退出——这正是报告能够“记录发现”而非“阻断执行”的前提,源码中明确注释了这一点;
  • --no-progress:去掉进度输出,保持结果干净;
  • --include dependencies,unlisted:只检查“未使用依赖”与“未声明依赖”两类(源码 TODO 注明:待依赖状况更规范后再逐步加入其他检查项);
  • --reporter markdown:输出 Markdown 表格,与仓库中提交的knip-report.md格式一致。

执行后还会做路径归一化:把表格中的位置列从packages/app/package.json:...统一替换为相对包目录的package.json:...,这正是你在 packages/app/knip-report.md 中看到 Location 列不含包路径前缀的原因。所有包的分析通过pLimit(os.cpus().length)按 CPU 核数并发执行。

四、本地与 CI 的行为差异:报告一致性如何被强制

--ci选项决定了报告不一致时的处理策略,对应 knip-reports.ts 中的isLocalBuild标志:

  • 本地构建(不带 --ci):若新生成的报告与已提交的knip-report.md不同,打印Knip report changed for <包路径>警告,并直接覆写该文件。开发者只需把更新后的 md 文件随 PR 一起提交;
  • CI 构建(带 --ci):若报告不同,则打印星号边框的提示块——“You have uncommitted changes to the knip reports of a package. To solve this, runyarn build:knip-reportsand commit all md file changes.”,打印冲突文件名与期望的完整报告内容后抛出异常使构建失败

这一机制让knip-report.md成为一份受 CI 约束的活文档:任何人新增/删除依赖后若没有重新生成报告,CI 会明确指出是哪个文件、期望内容是什么,修复路径唯一且清晰。

五、实战操作指引

在仓库中维护packages/app的依赖时,可遵循以下流程(仅涉及查看与重新生成,不修改仓库既有结构):

  1. 查看当前基线:直接阅读 packages/app/knip-report.md,对照 packages/app/package.json 的Location行列号定位具体依赖声明;
  2. 改动依赖后重新生成报告:在仓库根目录执行yarn build:knip-reports packages/app(本地模式会自动覆写报告文件);
  3. 将变化后的packages/app/knip-report.md与依赖变更一起提交;
  4. 如需批量检查,省略包路径参数即可分析全部工作区包;CI 中该命令会以--ci模式运行,报告漂移将直接失败。

最后需要说明适用前提:本文所有结论基于当前仓库快照(根包版本1.55.0-next.2)。报告中 Location 列的行号对应报告生成时刻的package.json内容,若该文件随后被编辑,行号可能与当前文件略有偏移,以重新运行yarn build:knip-reports的输出为准。

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 6:45:57

二维差分数组详解:从矩形批量更新到前缀和的高效算法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 6:45:45

老旧安卓机也能跑30fps?AI美颜特效渲染优化实践拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 6:41:30

Hyperswitch API 返回 429 时如何区分速率限制与 API 对象锁定

Hyperswitch API 返回 429 时如何区分速率限制与 API 对象锁定 【免费下载链接】hyperswitch Open source, composable payments platform | PCI compliant | SaaS and Self-host options | Enables connectivity to multiple payment, payout, fraud, vault and tokenization …

作者头像 李华
网站建设 2026/9/13 6:41:06

HTML基础语法入门:从标签结构到实战避坑完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 6:39:36

Vue nextTick 原理:microtask 与 DOM 更新时机深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华