注册源

添加于:v11.23.0

The registries setting in pnpm-workspace.yaml declares each registry a project installs from, once, keyed by the registry's URL. 关于某个注册源,pnpm 所知的一切都保存在其条目中:路由到它的作用域、它响应的裸说明符前缀,以及它背后服务器的状况。

pnpm-workspace.yaml
registries:
  https://npm.corp.example.com/:
    serverType: artifactory
    scopes: ["@acme", "@corp-tools"]
    prefix: work
  https://verdaccio.corp.example.com/:
    scopes: ["@"]
    supportsTimeField: true

URL 之所以是键,是因为条目中的每个事实都是关于该服务器的事实。如果 tarball 布局改为以作用域为键,它就会绑定到该作用域当前指向的对象,而两名开发者如果作用域解析结果不同,就会写出对哪些 URL 可以省略存在分歧的锁文件。

一个条目可能带有:

字段 类型 它告诉了什么
scopes string[] 路由到此注册源的包作用域。
前缀 string 此注册源所响应的裸说明符前缀。
serverType string How the server lays out tarball URLs: npm, artifactory, or pnpr.
supportsTimeField boolean 服务器的简化元数据是否带有 time 字段。

其他任何字段都会被拒绝。 In particular, credentials (_authToken, _auth, _password, username, tokenHelper) and TLS material (ca, cafile, cert, certfile, key, keyfile) are refused rather than silently ignored. pnpm-workspace.yaml is committed to the repository, so they belong in .npmrc (e.g. //npm.corp.example.com/:_authToken=...). 出于同样原因,内嵌 user:pass@ 凭据的 URL 键会被拒绝。

将包路由到注册源#

scopes#

其包从此注册源解析的作用域,需以 @ 为前缀。 A bare "@" routes the scope-less default registry, the same registry the registry setting names:

pnpm-workspace.yaml
registries:
  https://npm.corp.example.com/:
    scopes: ["@acme"]
  https://registry.internal.example.com/:
    scopes: ["@"]

一个作用域只能解析到一个注册源,因此从两个条目路由同一作用域是错误的。

prefix#

此注册源所响应的命名注册源前缀,例如 "lib": "work:^2.0.0":

pnpm-workspace.yaml
registries:
  https://npm.work.example.com/:
    prefix: work
pnpm add work:@corp/lib@^2.0.0

每个条目最多声明一个前缀,且两个条目不能声明相同的前缀:前缀是注册源在锁文件包键(foo@work:1.0.0)中的身份,因此第二种写法会把来自同一注册源的同一个包键控两次。

Prefixes declared here follow the same rules as the deprecated namedRegistries setting they replace: the built-in gh: and npmjs: aliases can be overridden by declaring their prefix on your own URL, reserved names are rejected, and packages resolved from a registry that declares a prefix get registry-qualified lockfile keys, whether a dependency names the prefix or a scopes entry routes it there.

描述服务器#

serverType#

并非所有注册源都像 npm 注册源那样组织 tarball URL。 pnpm omits a tarball URL from pnpm-lock.yaml when it can rebuild the URL from the package's name, version, and registry. The lockfile then carries no host-specific URL for that package, and renaming or moving the registry does not churn the lockfile. Whether pnpm can rebuild a URL depends on the server, and serverType is where you declare it:

serverType 含义
未声明 严格:只有当 tarball URL 恰好是规范的 npm 布局 URL(<registry>/<name>/-/<scopeless-name>-<version>.tgz)时,才会将其省略。除 registry.npmjs.org 之外的每个注册源,默认都按这种方式读取。
npm 该服务器的行为与 registry.npmjs.org 相同,带作用域的包既可以从百分号编码的路径(/@acme%2Fwidget/...)提供,也可以从未编码的路径提供。公共注册源的忠实镜像或缓存代理就属于这一类。对 registry.npmjs.org 本身而言是内置的。
artifactory 该服务器会在带作用域包的 tarball 文件名中重复作用域:@acme/widget/-/@acme/widget-1.0.0.tgz,而 npm 布局会将其去掉(@acme/widget/-/widget-1.0.0.tgz)。
pnpr The server serves a version's tarball at <registry>/<name>@<version>, such as @acme/widget@1.0.0.

对于 JFrog Artifactory 注册源,这决定了锁文件是为每个带作用域的包都记录一个特定主机的 tarball URL,还是一个都不记录:

pnpm-workspace.yaml
registries:
  https://acme.jfrog.example.com/artifactory/api/npm/npm-virtual/:
    serverType: artifactory
    scopes: ["@acme"]

常见服务器的取值:

服务器 serverType
JFrog Artifactory artifactory
GitLab 软件包注册源 artifactory. It uses the same layout, repeating the scope in the filename.
公共 npm 注册源的忠实镜像或缓存代理 npm
pnpr pnpr
Verdaccio, Sonatype Nexus, Azure Artifacts None needed. They serve the exact canonical npm layout, which the strict default already reconstructs.
GitHub Packages None. Its download URLs contain a content digest that cannot be derived from the package's identity, so they are kept in the lockfile.
GitHub Enterprise Server None. It serves a scoped package only from the percent-encoded path, which the strict default keeps in the lockfile and requests verbatim.

布局只能显式声明,从不推断:虚拟仓库可以同时提供两种布局,这取决于每个包是从上游同步的还是本地发布的,因此 pnpm 没有任何注册源层面的信号可供探测。显式声明也能让错误的取值变成可修复的配置问题,而不是静默的故障。

注意

serverType 是关于服务器的声明,只有服务器的运营者才能作出它,而锁文件依赖于它:被省略的 tarball URL 会在每次安装时按声明的布局重建,包括 --frozen-lockfile 安装。 Declare a layout the server actually serves, and expect a one-time lockfile diff after declaring one. URLs that pnpm can now rebuild disappear from the lockfile on the next install that writes it.

supportsTimeField#

该注册源的精简元数据是否带有 time 字段。 registry.npmjs.org 的没有,因此默认值为 false,而 minimumReleaseAge 这类基于时间的解析功能也会回退到体积大得多的完整元数据文档。 A registry that does carry it (Verdaccio v5.15.1+ and several proxies) is worth declaring:

pnpm-workspace.yaml
registries:
  https://verdaccio.corp.example.com/:
    scopes: ["@"]
    supportsTimeField: true

这是 registrySupportsTimeField 设置按注册源的形式。回退是按注册源决定的:需要完整元数据的单个注册源不再让其他注册源也付出该代价,而对于项目未描述的每个注册源,registrySupportsTimeField 仍是答案。

设置可以放在哪里#

该设置应放在 pnpm-workspace.yaml 中,而不是 .npmrc 或全局配置中,因为锁文件依赖它:如果一位开发者省略了 tarball URL,而另一位重建出的结果不同,冻结安装就会失败。

The global configuration file (config.yaml) may declare the routes (scopes and prefix) so that a scope or an alias like work: applies to every project on the machine. 服务器描述(serverType 和 supportsTimeField)只从 pnpm-workspace.yaml 读取,原因如上。

An entry that declares no routes describes a registry configured elsewhere. For example, the default registry set in .npmrc. 这样的条目只有在其 URL 是项目实际用于解析的地址时才生效;pnpm 会对匹配不到任何已配置注册源的条目给出警告,否则它们会毫无作用地留在那里(过期的 URL、已迁移的作用域)。

与 pnpm-workspace.yaml 中的其他注册源 URL 一样,该设置的 URL 键中不会展开环境变量,原因也相同:该文件会被提交到仓库,而把环境变量展开到请求目标中可能把机密泄露给攻击者控制的主机。含有 ${...} 占位符的键会被忽略。

旧的形式#

在 v11.23.0 之前,registries 将作用域映射到 URL,其中 default 键用于指定主注册源:

pnpm-workspace.yaml
registries:
  default: https://registry.npmjs.org/
  "@acme": https://npm.corp.example.com/

这种形式仍被接受,行为与以前相同。同一个映射中不能混用两种结构。 An entry whose value is a string is a scope route, and a scope route keyed by a URL is an error.

namedRegistries 设置已弃用,改用 prefix。它仍会被读取,但只用于 registries 未声明的前缀;当两者都声明了前缀时,pnpm 会给出警告。