ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

pnpm outdated --long 实战:Details 列回归包主页信息与过时依赖检查机制全解

pnpm outdated --long 实战:Details 列回归包主页信息与过时依赖检查机制全解 pnpm outdated --long 实战Details 列回归包主页信息与过时依赖检查机制全解【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm本文基于当前仓库中的变更说明 .changeset/outdated-long-homepage-details.md 展开讲解pnpm outdated命令的--long选项如何重新在 Details 列中填充依赖包的主页homepage信息对应上游 issue #14886 的回归修复并结合源码剖析pnpm outdated的完整选项、表格/列表/JSON 三种输出形态以及一个依赖何时会被判定为过时的底层判定逻辑帮助你在维护依赖时既能看清版本差距也能直接获得包主页这类决策所需的上下文。一、变更背景--long的 Details 列为什么曾经空了本次变更的 changeset 内容非常简短--- pacquet: patch --- pnpm outdated --long fills the Details column with the package homepage again它说明这是一次 patch 级修复pnpm outdated --long会再次在 Details 列中填充包的主页信息。要理解这个again的含义需要先了解--long的设计意图。在命令帮助文本中见 help()对--long的描述是By default, details about the outdated packages (such as a link to the repo) are not displayed. To display the details, pass this option.即默认情况下pnpm outdated只显示 Package / Current / Latest 三列加上--long后才会展示详情如主页链接、废弃提示。之所以会出现主页消失的回归关键在于注册表元数据的获取策略在 outdatedDepsOfProjects 中解析器通过createResolver创建其fullMetadata的取值是fullMetadata: opts.fullMetadata true || Boolean(opts.minimumReleaseAge),而从命令入口 handler 可以看到fullMetadata正是由opts.long直接传入outdatedDepsOfProjects(packages, packageParams, { ...opts, fullMetadata: opts.long, ... })也就是说不带--long时pnpm 只拉取经过裁剪的轻量元数据versions、dist-tags 等homepage字段根本不在返回的数据里带--long时才会拉取完整 manifestDetails 列才有内容可渲染。回归的本质就是完整元数据没有按预期被请求/传递而修复后 Details 列恢复填充 homepage。二、pnpm outdated的完整用法与全部选项pnpm outdated用于检查项目依赖中哪些已经过时。它的用法签名是pnpm outdated [pkg ...]支持用包名参数含通配符把检查范围缩小到一部分依赖。以下选项完整继承自仓库中的命令定义见 rcOptionsTypes / cliOptionsTypes / shorthands / help选项简写说明--compatible只打印满足 package.json 中版本范围specs的最新版本--long显示过时包的详情如主页链接同时触发拉取完整元数据--recursive-r在子目录中的每个包 / workspace 的每个包里检查过时依赖--no-table以列表形式打印适合小尺寸终端等价于--formatlist--prod-P只检查dependencies和optionalDependencies--dev-D只检查devDependencies--no-optional不检查optionalDependencies--format format输出格式table默认、list、json--include-github-actions同时检查工作流与 action 文件中的 GitHub Actions 依赖--sort-by指定排序方式目前仅支持name帮助文本中给出的示例命令可以原样复制使用pnpm outdated pnpm outdated --long pnpm outdated gulp-* babel/core其中最后一条演示了按参数过滤依赖子集的能力params在 handler 中会经createMatcher转成匹配器见 outdatedDepsOfProjects 中的match参数只有名称匹配的依赖才参与检查。三、--long在三种输出格式下的具体形态--long并不是简单地多加一列它在 table、list、json 三种格式下各有不同的渲染路径实现集中在 outdated.ts 的渲染函数群。3.1 table 格式Details 列与动态列宽在 renderOutdatedTable 中默认列是Package、Current、Latest三列当opts.long为真时追加第四列Details并调用 renderDetails 作为该列的渲染函数if (opts.long) { columnNames.push(Details) columnFns.push(renderDetails) }值得注意的实现细节Details 列的宽度不是按终端自适应的而是根据未废弃且带有 homepage 的包计算出的最宽 homepage 长度下限 40并开启wrapWord: trueconst detailsColumnMaxWidth outdatedPackages .filter(pkg pkg.latestManifest !pkg.latestManifest.deprecated) .reduce((maxWidth, pkg) { const cellWidth pkg.latestManifest?.homepage?.length ?? 0 return Math.max(maxWidth, cellWidth) }, 40)而 renderDetails 的输出规则是若最新版本被注册表标记为 deprecatedlatestManifest.deprecated是字符串提示语先以红色加粗输出该废弃说明若 manifest 中带有homepage再以带下划线样式输出该 URL两者都没有时返回空字符串Details 列显示为空。也就是说Details 列展示的是废弃警告 主页链接两类决策辅助信息——这正是 changeset 所说 fills the Details column with the package homepage again 的落点。3.2 list 格式详情换行追加在版本行之后renderOutdatedList 中--long时把renderDetails的结果以换行方式追加在包名 / current latest之后仅在 details 非空时追加if (opts.long) { const details renderDetails(outdatedPkg) if (details) { info \n${details} } }3.3 json 格式--long附带完整的 latestManifest在 renderOutdatedJSON 中默认每个包输出current、latest、wanted、isDeprecated、dependencyType五个字段而--long会额外挂上整个latestManifest即注册表返回的完整 manifesthomepage自然也在其中if (opts.long) { acc[outdatedPkg.packageName].latestManifest outdatedPkg.latestManifest }对 CI 脚本而言pnpm outdated --long --formatjson是获取结构化详情包括 homepage最可靠的方式。3.4 recursive 模式同样支持recursive.ts 中outdatedRecursive的处理与单项目一致同样以fullMetadata: opts.long调用outdatedDepsOfProjects见 recursive.ts#L60-L64并在聚合表格中同样按--long追加Details列见 recursive.ts#L144-L145。因此在 workspace 根目录执行pnpm outdated -r --long时跨项目聚合表中的 Details 列同样会展示 homepage。四、过时是如何判定的源码级逻辑理解了 Details 列再回溯一下行数据从何而来。核心判定在 outdated() 中对每个依赖覆盖dependencies、devDependencies、optionalDependencies三个字段执行前置过滤manifest 三个依赖字段全空时直接返回空数组packageHasNoDeps没有wantedLockfile时抛出OUTDATED_NO_LOCKFILE错误提示先运行pnpm install引用为本地形态link:/file:/workspace:前缀的依赖被跳过因为它们没有注册表上的latest可比对见 isLocalRef命中ignoreDependencies匹配器的依赖被跳过catalog:协议的 specifier 会先经 catalog 解析替换为真实版本范围replaceCatalogProtocolIfNecessary。解析 latest对每个依赖调用resolveLatest传入{ alias, bareSpecifier }与compatible标志--compatible的生效点若 resolver 返回 null不认领该依赖则静默跳过。判定是否过时见 outdated.ts#L178满足以下任一条件即列入结果——wanted ! currentpackage.json 声明的版本与 lockfile 中实际安装版本不一致依赖未同步安装isLowerVersion(wanted, latestManifest.version)当前 wanted 版本低于注册表 latestlatestManifest.deprecatedlatest 版本已被废弃。比较前会先把 lockfile ref 归一化为显示版本displayVersionsemver 型 dep-path 取解析出的版本从而让仅 peer 哈希变化同 semver、不同(peer-hash)不会被误报为过时URL/git 型 ref 则保留原始 ref使得 commit/路径变化仍会触发提示。isLowerVersion内部用semver.lt对非 semver 字符串直接返回 false交由 ref 比较兜底。输出结果按packageName排序返回元素结构为 OutdatedPackagealias、belongsTo、current、latestManifest、packageName、wanted、workspacelatestManifest正是 Details 列的数据源。此外--include-github-actions引入的 GitHub Actions 依赖会被 toOutdatedAction 包装成同样的OutdatedItem其homepage来自 action 元数据因此 Actions 条目在--long下同样会在 Details 列展示主页。五、退出码与工程化用法handler 的返回 固定约定return { output, exitCode: outdatedPackages.length 0 ? 0 : 1, }即存在任何过时依赖时退出码为 1这使pnpm outdated可以直接作为 CI 中的依赖健康度门禁。推荐的工程化组合# 本地查看表格 详情列homepage / 废弃提示 pnpm outdated --long # 小终端 / 日志友好的列表形态 pnpm outdated --no-table --long # CI 中结构化消费含 latestManifest.homepage pnpm outdated --long --formatjson # workspace 根目录跨项目检查 pnpm outdated -r --long # 只看部分依赖 pnpm outdated babel/* webpack-* # 纳入 GitHub Actions 依赖检查 pnpm outdated --include-github-actions --long使用前提与限制pnpm outdated依赖 lockfile 存在缺失时会报OUTDATED_NO_LOCKFILE且检查 latest 需要访问对应 registry受--tag、代理、minimumReleaseAge等通用配置影响当设置了minimumReleaseAge时也会强制fullMetadata见 outdatedDepsOfProjects.ts#L60。六、关键文件索引变更说明.changeset/outdated-long-homepage-details.md命令入口、帮助文本、三种格式渲染与renderDetailspnpm11/deps/inspection/commands/src/outdated/outdated.tsrecursive 模式实现pnpm11/deps/inspection/commands/src/outdated/recursive.ts过时判定核心outdated()pnpm11/deps/inspection/outdated/src/outdated.ts项目级入口与fullMetadata传递pnpm11/deps/inspection/outdated/src/outdatedDepsOfProjects.ts总结pnpm outdated --long的价值在于把版本差多少升级为该不该升、去哪看——Details 列恢复 homepage 填充后配合 deprecated 提示开发者在升级决策时可以直接获得包的主页入口而这一能力的技术前提是--long触发fullMetadata拉取完整注册表 manifest理解这条从 CLI 选项到 resolver 参数的链路才能正确预期 Details 列在何种场景下有内容、何时为空。【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进