AIRI Monorepo 中的 pnpm 配置体系:以 pnpm-workspace.yaml 为核心的设置分层与实战

AIRI Monorepo 中的 pnpm 配置体系:以 pnpm-workspace.yaml 为核心的设置分层与实战 AIRI Monorepo 中的 pnpm 配置体系以 pnpm-workspace.yaml 为核心的设置分层与实战【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi本篇以 AIRI 仓库内置的 pnpm 技能文档 core-config.md 为主体系统讲解 pnpm 当前的配置分层模型所有安装与解析设置收敛到pnpm-workspace.yaml与全局config.yamlYAML、camelCase 键名.npmrc只保留认证与 registry 凭据。结合 AIRI 这个 pnpm monorepo 的真实配置你可以掌握如何在大型工作区中集中管理依赖版本catalog、强制版本overrides、构建脚本审批allowBuilds与包管理器/运行时锁定packageManager / devEngines。一、配置二分法设置与凭据严格分离当前 pnpm 最重要的配置概念是设置settings与凭据credentials分属两类文件。文档将其归纳为一张表类别存放位置格式全部 pnpm/安装设置nodeLinker、hoistPattern、autoInstallPeers、overrides、catalog等pnpm-workspace.yaml项目级与config.yaml全局YAMLcamelCase键名认证与 registry 凭据_authToken、cert、key等.npmrc项目级gitignore与全局rcINI这里有三条必须牢记的行为变化pnpm不再读取package.json中的pnpm字段该字段被彻底弃用.npmrc现在仅用于认证/registry 凭据其他一切设置都归pnpm-workspace.yamlYAML 中的键名是camelCase如nodeLinker而不是旧.npmrc时代沿用的 kebab-case。AIRI 仓库本身就是这一模型的完整示范根目录不存在.npmrc凭据不落库全部解析行为都由 pnpm-workspace.yaml 声明SKILL.md 中的技能说明也强调在 pnpm 项目中检查pnpm-workspace.yaml获取设置与工作区结构只在认证场景看.npmrc。二、pnpm-workspace.yaml主配置文件该文件放在 workspace/项目根目录即使是单包项目也用这个文件存放 pnpm 设置。文档给出的完整示例覆盖了近期的核心设置项# Workspace packages (omit for a single-package repo) packages: - packages/* - apps/* - !**/test/** # Common install settings (camelCase) nodeLinker: isolated # isolated (default) | hoisted | pnp autoInstallPeers: true strictPeerDependencies: false savePrefix: ^ saveExact: false hoistPattern: - *eslint* - *babel* publicHoistPattern: [] shamefullyHoist: false dedupeDirectDeps: false resolutionMode: highest # highest | time-based | lowest-direct # Centralized version management catalog: react: ^18.2.0 # Force dependency versions (root only) overrides: lodash: ^4.17.21 foo^1.0.0bar: ^2.0.0 # Extend/patch broken package manifests packageExtensions: react-redux: peerDependencies: react-dom: * # Peer dependency rules peerDependencyRules: ignoreMissing: - babel/* allowedVersions: react: 17 || 18逐段解读各设置组的语义安装行为设置nodeLinker决定 node_modules 的链接形态isolated为默认另有hoisted与pnpautoInstallPeers控制是否自动安装 peer 依赖savePrefix/saveExact控制pnpm add写入版本范围时使用的前缀^、~或精确hoistPattern/publicHoistPattern/shamefullyHoist控制虚拟 store 中的提升行为resolutionMode在多个可用版本中的取舍策略为highest、time-based、lowest-direct三选一。overrides强制依赖版本的唯一入口且只在根项目生效。键可以是包名也可以是直接依赖传递依赖的嵌套路径用于把某个特定上游引入的间接依赖钉死到指定版本。packageExtensions在不改源码的前提下修补第三方包的 manifest典型用途是为缺少 peer 声明的包补上peerDependencies。peerDependencyRules对 peer 依赖的告警/报错做规则化处理如忽略缺失ignoreMissing或放宽版本要求allowedVersions。AIRI 的真实 pnpm-workspace.yaml一个生产级范本AIRI 根目录的 pnpm-workspace.yaml 展示了上述机制在大型 monorepo 中的组合用法几个值得注意的点catalogMode: prefer minimumReleaseAge: 4320 minimumReleaseAgeExclude: - moeru/* - proj-airi/* # ... 其他内部/自有 scope shellEmulator: true packages: - packages/** - plugins/** - integrations/** - services/** - examples/** - docs/** - engines/** - apps/** - server/** - !**/dist/** overrides: types/hast: catalog: axios: npm:feaxios^0.0.23 hono: 4.13.3 # ... npm: 别名替换若干上游包 patchedDependencies: mineflayer-pathfinder: patches/mineflayer-pathfinder.patch pixi-live2d-display: patches/pixi-live2d-display.patch uiohook-napi1.5.5: patches/uiohook-napi1.5.5.patchpackages使用**通配并配!**/dist/**负向排除说明工作区 glob 支持任意深度匹配与排除规则AIRI 用它把packages/、apps/、server/等九个顶层目录全部纳入同一 workspace 并共用一个 lockfile。overrides中直接写catalog:表示该包以 catalog 中登记的版本为准让强制版本与集中版本管理打通——types/hast: catalog:就是把全仓所有types/hast解析结果钉到 catalog 值。npm:别名 overrides 组合axios: npm:feaxios^0.0.23表示全仓任何位置引入的axios都会被替换为feaxios这个别名包这是一种典型的依赖换皮手段patchedDependencies则把 patches/ 目录下的补丁文件如 patches/uiohook-napi1.5.5.patch应用到了指定版本之上两者都属于不修改上游源码即可修正依赖行为的官方机制。供应链安全设置minimumReleaseAge: 4320仅接受发布满指定小时数的版本配合minimumReleaseAgeExclude对自有 scope 豁免这正是新版供应链接近安全配置项的实际落地技能文档目录中的 features-supply-chain-security.md 对该主题有更完整的论述。三、catalog集中化版本管理的仓库级应用文档示例中的catalog只有单条目AIRI 的 pnpm-workspace.yaml 则维护了 400 余条目的 catalog覆盖vue、vite、typescript、electron、mineflayer全家桶等全部关键依赖。其使用方式分三层子包声明版本为catalog:。以 packages/plugin-sdk/package.json 为例dependencies: { moeru/eventa: catalog:, moeru/std: catalog:, proj-airi/plugin-protocol: workspace:*, nanoid: catalog: }子包不再写具体版本只引用 catalog 键workspace:*则用于指向同 workspace 内的本地包。全仓apps/、packages/、integrations/下的大量package.json都是这一模式。命名 catalogcatalogs为特定依赖组建独立版本集。AIRI 在根配置中声明了vitest与xsai两个命名 catalogpnpm-workspace.yamlcatalogs: vitest: vitest/browser-playwright: ^4.1.11 vitest/coverage-v8: ^4.1.11 vitest: ^4.1.11 xsai: unspeech: ^0.1.16子包中即可引用catalog:vitest取该命名空间下的版本例如根 package.json 里的vitest/browser-playwright: catalog:vitest、vitest: catalog:vitest。这样 vitest 生态可以整体升级而互不干扰。catalogMode: prefer让 catalog 优先作为版本来源参与解析。解析结果最终沉淀进 pnpm-lock.yaml 的catalogs段每个包记录specifier与实际version供审计与pnpm ci冻结安装使用。这套机制的价值在于升级vue只需改一行 catalog 条目而不是逐个扫描 40 多个package.jsonAIRI 根 package.json 中的up脚本taze -w -r -I pnpm prune pnpm dedupe则用 taze 工具批量刷新版本后配合 prune/dedupe 收尾构成完整的升级工作流。四、全局配置config.yaml 的位置用户级非认证设置存放在全局 YAML 文件config.yaml按平台的查找顺序为$XDG_CONFIG_HOME/pnpm/config.yaml若设置了该环境变量Linux~/.config/pnpm/config.yamlmacOS~/Library/Preferences/pnpm/config.yamlWindows~/AppData/Local/pnpm/config/config.yaml同目录下还有一个名为rc的伴生全局文件只承载 registry/认证设置。这条分层与项目级形成对照项目行为看pnpm-workspace.yaml机器级默认看config.yaml密钥永远只进.npmrc/rc。五、workspace 内按包设置packageConfigs新版 pnpm 取消了子包各自的.npmrc改为在根pnpm-workspace.yaml中用packageConfigs为单个包覆写设置。文档给出两种形态packageConfigs: # Map form: keyed by package name project-1: saveExact: true project-2: savePrefix: ~ # Array form: pattern-matched rules # - match: [project-1, project-2] # modulesDir: node_modules # saveExact: trueMap 形态以包名为键精确匹配某个 workspace 包数组形态以match做模式匹配可对一组包批量下发规则如统一saveExact、modulesDir等。对多子包 monorepo 来说这取代了过去在子目录散落.npmrc的做法让每个包的行为差异也在根文件内一处可查、一处可改。六、.npmrc只装认证且按优先级读取项目级认证文件保持在.npmrc但要加入 .gitignore 防止 token 入库。认证文件的读取优先级从高到低workspace root/.npmrc项目级gitignoredpnpm config/auth.ini由pnpm login写入~/.npmrc兼容 npm 的兜底文档给出的标准 INI 示例引用环境变量注入 token而非明文//registry.npmjs.org/:_authToken${NPM_TOKEN} myorg:registryhttps://npm.myorg.com/ //npm.myorg.com/:_authToken${MYORG_TOKEN}注意 registry 的非机密配置默认 registry、scope 映射、命名 registry 别名应写在pnpm-workspace.yaml而不是.npmrcregistries: default: https://registry.npmjs.org/ my-org: https://private.example.com/ # Named registry aliases usable as a prefix, e.g. pnpm add work:corp/lib namedRegistries: work: https://npm.work.example.com/namedRegistries允许把私有 registry 起别名后作为前缀使用pnpm add work:corp/lib使安装命令不必再携带完整 URL。安全要点自 v11 起项目级.npmrc中 registry/proxy URL 与凭据键的环境变量展开被禁用目的是防止恶意仓库通过伪造.npmrc窃取已注入的环境变量密钥。动态 token 行应放入用户级认证文件第 2 优先级的auth.ini。AIRI 仓库根目录没有提交任何.npmrc与凭据不进库、认证走本地/CI secret的约定一致。七、pnpm config 命令读取与写入pnpm config子命令是操作上述配置的入口行为同样遵循设置进 YAML、认证进 rc的分离# Writes to global config.yaml / rc by default pnpm config set nodeVersion 22.0.0 pnpm config set --locationproject nodeVersion 22.0.0 # writes pnpm-workspace.yaml # JSON values create arrays/objects pnpm config set --locationproject --json allowBuilds {react: true} # get/list print JSON (no longer INI) since v11 pnpm config get nodeLinker pnpm config get allowBuilds.react pnpm config list行为要点不带--location时写入全局config.yaml/rc加--locationproject才写入pnpm-workspace.yaml--json把值按 JSON 解析从而能写入数组/对象如allowBuilds这种映射型设置v11 起get/list的输出统一为JSON不再是 INI方便脚本消费get支持allowBuilds.react这样的点路径取值。八、环境变量只认 pnpm_config_*环境变量注入设置的命名空间也发生了变化使用pnpm_config_*或大写PNPM_CONFIG_*不再读取npm_config_*。pnpm_config_save_exacttrue pnpm add foo这对 CI 场景意味着沿用 npm 时代npm_config_*的注入脚本会静默失效需要按新前缀改写。九、改名/移除的设置项对照表从旧版.npmrc时代迁移时以下设置项已更名或删除文档给出了完整对照旧名已移除替代项说明onlyBuiltDependencies、neverBuiltDependencies、ignoredBuiltDependencies、onlyBuiltDependenciesFileallowBuilds: { name: true\|false }单一映射表统一控制构建脚本审批managePackageManagerVersions、packageManagerStrict、packageManagerStrictVersion、COREPACK_ENABLE_STRICTpmOnFail: download\|ignore\|warn\|error实际运行的 pnpm 版本与声明版本不一致时的行为useNodeVersiondevEngines.runtime写在package.json运行时锁定auditConfig.ignoreCvesauditConfig.ignoreGhsas改用 GHSA 编号allowNonAppliedPatchesallowUnusedPatchesignorePatchFailures已删除补丁失败现在总是抛错package.json#pnpm字段pnpm-workspace.yaml完全不再读取AIRI 的根 pnpm-workspace.yaml 中的allowBuilds就是新命名下的完整实例逐包列出true/false审批结果例如esbuild: true、sharp: true、better-sqlite3: false并带注释说明simple-git-hooks: false是为shellEmulator: true场景下的已知问题所做的工作区规避workaround。旧的四个构建依赖白名单设置由此收敛为一张表。十、package.json 中的包管理器与运行时锁定package.json在新模型中只保留两件事packageManager字段与devEngines声明。文档示例{ packageManager: pnpm10.0.0, devEngines: { packageManager: { name: pnpm, version: 11.0.0 12.0.0, onFail: download }, runtime: { name: node, version: 22.x, onFail: download } } }语义差异packageManager要求精确版本如pnpm10.0.0devEngines.packageManager支持版本范围解析出的实际版本会写入 lockfile两者的onFail都可以通过设置项pmOnFail/runtimeOnFail在不改 manifest 的情况下整体覆盖。AIRI 的根 package.json 声明了packageManager: pnpm11.24.0即仓库锁定的 pnpm 主版本正是 11.x——上文所有 v11 行为变化config 输出 JSON、pnpm字段弃用、项目级.npmrc禁用环境变量展开等都是该仓库的实际运行前提。技能文档 SKILL.md 也注明本技能基于 pnpm 10.x 生成同时覆盖 v11 的行为变化config 拆分、isolated global packages、allowBuilds、pmOnFail、global virtual store与本仓库pnpm11.24.0的声明相互印证。十一、关键要点小结所有 pnpm 设置都放pnpm-workspace.yamlcamelCase或全局config.yaml.npmrc只保留认证/registry 凭据并应 gitignore。package.json#pnpm字段与npm_config_*环境变量都不再被读取环境变量前缀为pnpm_config_*/PNPM_CONFIG_*。工作区内按包差异化设置用packageConfigsMap 或模式匹配数组两种形态子包级.npmrc已取消。构建脚本审批统一为一张allowBuilds映射表AIRI 根配置中可看到 30 余条真实审批记录包管理器严格性统一为pmOnFail一个设置。pnpm config get/list自 v11 起输出 JSON--locationproject把set的落点从全局切到pnpm-workspace.yaml。版本集中管理走catalog/ 命名catalogsAIRI 使用catalog:与catalog:vitest引用配合overrides、patchedDependencies与供应链设置minimumReleaseAge等构成完整的依赖治理面。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考