111k

命名空间

使用命名空间支持配置和使用多个资源注册表。

命名空间注册表允许你在一个项目中配置多个资源来源。这意味着你可以从不同的注册表安装组件、库、工具、AI 提示、配置文件和其他资源,无论它们是公开的、第三方的,还是你自己定制的私有库。

目录


概览

注册表命名空间以 @ 开头,用于组织和引用来自不同来源的资源。资源可以是任何类型的内容:组件、库、工具、hooks、AI 提示、配置文件、主题等。例如:

  • @shadcn/button - 来自 shadcn 注册表的 UI 组件
  • @v0/dashboard - 来自 v0 注册表的仪表盘组件
  • @ai-elements/input - 来自 AI elements 注册表的 AI 提示输入
  • @acme/auth-utils - 来自你们公司私有注册表的认证工具
  • @ai/chatbot-rules - 来自 AI 资源注册表的 AI 提示规则
  • @themes/dark-mode - 来自主题注册表的主题配置

去中心化命名空间系统

我们刻意将命名空间系统设计为去中心化。对于开源命名空间,有一个中心化的开源注册表索引,但你完全可以创建并使用任何你想要的命名空间。

这种去中心化的方式让你可以根据组织的实际需求,完全自由地组织资源。

你可以为不同用途创建多个注册表:

components.json
{
  "registries": {
    "@acme-ui": "https://registry.acme.com/ui/{name}.json",
    "@acme-docs": "https://registry.acme.com/docs/{name}.json",
    "@acme-ai": "https://registry.acme.com/ai/{name}.json",
    "@acme-themes": "https://registry.acme.com/themes/{name}.json",
    "@acme-internal": {
      "url": "https://internal.acme.com/registry/{name}.json",
      "headers": {
        "Authorization": "Bearer ${INTERNAL_TOKEN}"
      }
    }
  }
}

这让你可以:

  • 按类型组织:将 UI 组件、文档、AI 资源等分开管理
  • 按团队组织:不同团队可以维护自己的注册表
  • 按可见性组织:公开资源与私有资源分开
  • 按版本组织:稳定版与实验版注册表分离
  • 避免命名冲突:由于没有中心化权威,你不需要担心命名空间冲突

多注册表配置示例

按资源类型

components.json
{
  "@components": "https://cdn.company.com/components/{name}.json",
  "@hooks": "https://cdn.company.com/hooks/{name}.json",
  "@utils": "https://cdn.company.com/utils/{name}.json",
  "@prompts": "https://cdn.company.com/ai-prompts/{name}.json"
}

按团队或部门

components.json
{
  "@design": "https://create.company.com/registry/{name}.json",
  "@engineering": "https://eng.company.com/registry/{name}.json",
  "@marketing": "https://marketing.company.com/registry/{name}.json"
}

按稳定性

components.json
{
  "@stable": "https://registry.company.com/stable/{name}.json",
  "@latest": "https://registry.company.com/beta/{name}.json",
  "@experimental": "https://registry.company.com/experimental/{name}.json"
}

快速开始

安装资源

配置完成后,你可以使用命名空间语法安装资源:

pnpm dlx shadcn@latest add @v0/dashboard

或者一次安装多个资源:

pnpm dlx shadcn@latest add @acme/header @lib/auth-utils @ai/chatbot-rules

快速配置

将注册表添加到你的 components.json

components.json
{
  "registries": {
    "@v0": "https://v0.dev/chat/b/{name}",
    "@acme": "https://registry.acme.com/resources/{name}.json"
  }
}

然后开始安装:

pnpm dlx shadcn@latest add @acme/button

注册表命名规范

注册表名称必须遵循以下规则:

  • @ 符号开头
  • 仅包含字母数字字符、连字符和下划线
  • 有效名称示例:@v0@acme-ui@my_company

资源的引用格式是:@namespace/resource-name


配置

命名空间注册表在 components.json 文件的 registries 字段中配置。

基础配置

配置注册表最简单的方式是使用 URL 模板字符串:

components.json
{
  "registries": {
    "@v0": "https://v0.dev/chat/b/{name}",
    "@acme": "https://registry.acme.com/resources/{name}.json",
    "@lib": "https://lib.company.com/utilities/{name}",
    "@ai": "https://ai-resources.com/r/{name}.json"
  }
}

注意: 当你运行 npx shadcn@latest add @namespace/resource-name 时,URL 中的 {name} 占位符会自动解析并替换为资源名称。例如,@acme/button 会变成 https://registry.acme.com/resources/button.json。更多细节请参见 URL 模式系统

高级配置

对于需要认证或额外参数的注册表,请使用对象格式:

components.json
{
  "registries": {
    "@private": {
      "url": "https://api.company.com/registry/{name}.json",
      "headers": {
        "Authorization": "Bearer ${REGISTRY_TOKEN}",
        "X-API-Key": "${API_KEY}"
      },
      "params": {
        "version": "latest",
        "format": "json"
      }
    }
  }
}

注意: ${VAR_NAME} 形式的环境变量会自动从你的环境变量(process.env)中展开。这适用于 URL、headers 和 params。例如,${REGISTRY_TOKEN} 会被替换为 process.env.REGISTRY_TOKEN 的值。有关如何使用环境变量的更多信息,请参见 认证与安全


URL 模式系统

注册表 URL 支持以下占位符:

{name} 占位符(必需)

{name} 占位符会被资源名称替换:

components.json
{
  "@acme": "https://registry.acme.com/{name}.json"
}

安装 @acme/button 时,URL 会变成:https://registry.acme.com/button.json 安装 @acme/auth-utils 时,URL 会变成:https://registry.acme.com/auth-utils.json

{style} 占位符(可选)

{style} 占位符会被当前样式配置替换:

{
  "@themes": "https://registry.example.com/{style}/{name}.json"
}

当样式设置为 new-york 时,安装 @themes/card 会解析为:https://registry.example.com/new-york/card.json

style 占位符是可选的。当你希望同一个资源提供不同版本时,可以使用它。例如,你可以针对每种样式提供不同版本的组件。


认证与安全

环境变量

使用环境变量安全地存储凭据:

components.json
{
  "registries": {
    "@private": {
      "url": "https://api.company.com/registry/{name}.json",
      "headers": {
        "Authorization": "Bearer ${REGISTRY_TOKEN}"
      }
    }
  }
}

然后设置环境变量:

.env.local
REGISTRY_TOKEN=your_secret_token_here

认证方式

Bearer Token(OAuth 2.0)

{
  "@github": {
    "url": "https://api.github.com/repos/org/registry/contents/{name}.json",
    "headers": {
      "Authorization": "Bearer ${GITHUB_TOKEN}"
    }
  }
}

在 Headers 中使用 API Key

components.json
{
  "@private": {
    "url": "https://api.company.com/registry/{name}",
    "headers": {
      "X-API-Key": "${API_KEY}"
    }
  }
}

基本认证

components.json
{
  "@internal": {
    "url": "https://registry.company.com/{name}.json",
    "headers": {
      "Authorization": "Basic ${BASE64_CREDENTIALS}"
    }
  }
}

查询参数认证

components.json
{
  "@secure": {
    "url": "https://registry.example.com/{name}.json",
    "params": {
      "api_key": "${API_KEY}",
      "client_id": "${CLIENT_ID}",
      "signature": "${REQUEST_SIGNATURE}"
    }
  }
}

多种认证方式

有些注册表需要同时使用多种认证方式:

components.json
{
  "@enterprise": {
    "url": "https://api.enterprise.com/v2/registry/{name}",
    "headers": {
      "Authorization": "Bearer ${ACCESS_TOKEN}",
      "X-API-Key": "${API_KEY}",
      "X-Workspace-Id": "${WORKSPACE_ID}"
    },
    "params": {
      "version": "latest"
    }
  }
}

安全注意事项

在使用命名空间注册表时,尤其是第三方或公开注册表时,安全性至关重要。我们是这样处理安全问题的:

资源校验

从注册表获取的所有资源在安装前都会根据注册表 item schema 进行校验。这可以确保:

  • 结构校验:资源必须符合预期的 JSON schema
  • 类型安全:资源类型会被验证(registry:uiregistry:lib 等)
  • 不会执行任意代码:资源是数据文件,而不是可执行脚本

环境变量安全

用于认证的环境变量:

  • 不会被记录:CLI 从不记录或显示环境变量值
  • 运行时展开:变量只会在需要时展开,不会被存储
  • 按注册表隔离:每个注册表都维护自己的认证上下文

安全配置示例:

components.json
{
  "registries": {
    "@private": {
      "url": "https://api.company.com/registry/{name}.json",
      "headers": {
        "Authorization": "Bearer ${PRIVATE_REGISTRY_TOKEN}"
      }
    }
  }
}

不要把真实 token 提交到版本控制中。请使用 .env.local

.env.local
PRIVATE_REGISTRY_TOKEN=actual_token_here

强制使用 HTTPS

我们强烈建议所有注册表 URL 都使用 HTTPS:

  • 加密传输:防止中间人攻击
  • 证书校验:确保你连接的是合法的注册表
  • 凭据保护:headers 和 token 在传输过程中会被加密
components.json
{
  "registries": {
    "@secure": "https://registry.example.com/{name}.json", // ✅ Good
    "@insecure": "http://registry.example.com/{name}.json" // ❌ Avoid
  }
}

内容安全

来自注册表的资源会被当作数据而不是代码处理:

  1. JSON parsing only: Resources must be valid JSON
  2. Schema validation: Must match the registry item schema
  3. File path restrictions: Files can only be written to configured paths
  4. No script execution: The CLI doesn't execute any code from registry resources

注册表信任模型

命名空间系统基于信任模型运行:

  • 你要信任自己安装的内容:只把你信任的注册表添加到配置里
  • 显式配置:注册表必须在 components.json 中明确配置
  • 不会自动发现注册表:CLI 不会自动添加注册表
  • 依赖透明:所有依赖都会在注册表 item 中清晰列出

给注册表运营者的最佳实践

如果你在运行自己的注册表:

  1. 始终使用 HTTPS:不要通过 HTTP 提供注册表内容
  2. 实现认证:私有注册表要求 API key 或 token
  3. 限流:保护你的注册表免受滥用
  4. 内容校验:在提供资源之前先进行校验

安全注册表示例:

components.json
{
  "@company": {
    "url": "https://registry.company.com/v1/{name}.json",
    "headers": {
      "Authorization": "Bearer ${COMPANY_TOKEN}",
      "X-Registry-Version": "1.0"
    }
  }
}

安装前检查资源

CLI 会清楚展示将要安装的内容。你可以使用下面的命令查看某个注册表 item 的 payload:

pnpm dlx shadcn@latest view @acme/button

这会把该注册表 item 的 payload 输出到控制台。


依赖解析

基础依赖解析

资源可以依赖来自不同注册表的内容:

registry-item.json
{
  "name": "dashboard",
  "type": "registry:block",
  "registryDependencies": [
    "@shadcn/card", // From default registry
    "@v0/chart", // From v0 registry
    "@acme/data-table", // From acme registry
    "@lib/data-fetcher", // Utility library
    "@ai/analytics-prompt" // AI prompt resource
  ]
}

CLI 会自动从各自的注册表中解析并安装所有依赖。

高级依赖解析

如果你正在开发注册表,或者需要定制第三方资源,了解依赖在内部是如何解析的很重要。

解析流程

当你运行 npx shadcn@latest add @namespace/resource 时,CLI 会执行以下步骤:

  1. 清除注册表上下文,从干净状态开始
  2. 从指定注册表获取主资源
  3. 递归解析依赖,从各自的注册表中获取
  4. 应用拓扑排序,确保正确的安装顺序
  5. 根据目标路径去重文件(后者覆盖前者)
  6. 深度合并配置(tailwind、cssVars、css、envVars)

这意味着如果你运行下面的命令:

pnpm dlx shadcn@latest add @acme/auth @custom/login-form

@custom/login-form 中的 login-form.ts 会覆盖 @acme/auth 中的 login-form.ts,因为它是最后解析的。

覆盖第三方资源

你可以利用依赖解析流程来覆盖任何第三方资源:把它们添加到你自定义资源的 registryDependencies 中,然后用你自己的自定义值覆盖它们。

示例:定制第三方按钮

假设你想定制 vendor 注册表中的一个按钮:

1. 原始 vendor 按钮@vendor/button):

button.json
{
  "name": "button",
  "type": "registry:ui",
  "files": [
    {
      "path": "components/ui/button.tsx",
      "type": "registry:ui",
      "content": "// Vendor's button implementation\nexport function Button() { ... }"
    }
  ],
  "cssVars": {
    "light": {
      "--button-bg": "blue"
    }
  }
}

2. 创建你自己的覆盖版本@my-company/custom-button):

custom-button.json
{
  "name": "custom-button",
  "type": "registry:ui",
  "registryDependencies": [
    "@vendor/button" // Import original first
  ],
  "cssVars": {
    "light": {
      "--button-bg": "purple" // Override the color
    }
  }
}

3. 安装你的自定义版本

pnpm dlx shadcn@latest add @my-company/custom-button

这会先安装 @vendor/button 中的原始按钮,然后用你自己的自定义值覆盖 cssVars

高级覆盖模式

扩展而不是替换

保留原始内容并添加扩展:

extended-table.json
{
  "name": "extended-table",
  "registryDependencies": ["@vendor/table"],
  "files": [
    {
      "path": "components/ui/table-extended.tsx",
      "content": "import { Table } from '@vendor/table'\n// Add your extensions\nexport function ExtendedTable() { ... }"
    }
  ]
}

这会先安装 @vendor/table 中的原始表格,然后把你的扩展添加到 components/ui/table-extended.tsx

局部覆盖(多文件资源)

只覆盖复杂组件中的某些文件:

custom-auth.json
{
  "name": "custom-auth",
  "registryDependencies": [
    "@vendor/auth" // Has multiple files
  ],
  "files": [
    {
      "path": "lib/auth-server.ts",
      "type": "registry:lib",
      "content": "// Your custom auth server"
    }
  ]
}

解析顺序示例

当你安装依赖多个资源的 @custom/dashboard 时:

dashboard.json
{
  "name": "dashboard",
  "registryDependencies": [
    "@shadcn/card", // 1. Resolved first
    "@vendor/chart", // 2. Resolved second
    "@custom/card" // 3. Resolved last (overrides @shadcn/card)
  ]
}

解析顺序:

  1. @shadcn/card - 安装到 components/ui/card.tsx
  2. @vendor/chart - 安装到 components/ui/chart.tsx
  3. @custom/card - 覆盖 components/ui/card.tsx(如果目标路径相同)

解析的关键特性

  1. 来源追踪:每个资源都知道自己来自哪个注册表,从而避免命名冲突
  2. 防止循环依赖:自动检测并阻止循环依赖
  3. 智能安装顺序:先安装依赖,再安装使用这些依赖的资源

版本管理

你可以使用查询参数为注册表资源实现版本管理。这样用户就可以固定特定版本,或者使用不同的发布通道。

基础版本参数

components.json
{
  "@versioned": {
    "url": "https://registry.example.com/{name}",
    "params": {
      "version": "v2"
    }
  }
}

这会将 @versioned/button 解析为:https://registry.example.com/button?version=v2

动态版本选择

使用环境变量来控制整个项目中的版本:

components.json
{
  "@stable": {
    "url": "https://registry.company.com/{name}",
    "params": {
      "version": "${REGISTRY_VERSION}"
    }
  }
}

这让你可以:

  • 在生产环境设置 REGISTRY_VERSION=v1.2.3
  • 按环境覆盖(开发、预发布、生产)

语义化版本

用范围支持实现语义化版本:

components.json
{
  "@npm-style": {
    "url": "https://registry.example.com/{name}",
    "params": {
      "semver": "^2.0.0",
      "prerelease": "${ALLOW_PRERELEASE}"
    }
  }
}

版本解析最佳实践

  1. 使用环境变量 来在不同环境之间控制版本
  2. 使用 ${VAR:-default} 语法 提供合理默认值
  3. 清楚记录版本方案,方便注册表用户理解
  4. 支持版本固定,以便构建结果可复现
  5. 实现版本发现 端点(例如 /versions/{name}
  6. 对版本化资源使用合适的缓存头 做缓存

CLI 命令

shadcn CLI 提供了多个用于命名空间注册表的命令:

添加资源

从任何已配置的注册表安装资源:

# Install from a specific registry
npx shadcn@latest add @v0/dashboard
 
# Install multiple resources
npx shadcn@latest add @acme/button @lib/utils @ai/prompt
 
# Install from URL directly
npx shadcn@latest add https://registry.example.com/button.json
 
# Install from local file
npx shadcn@latest add ./local-registry/button.json

查看资源

在安装前检查注册表 item:

# View a resource from a registry
npx shadcn@latest view @acme/button
 
# View multiple resources
npx shadcn@latest view @v0/dashboard @shadcn/card
 
# View from URL
npx shadcn@latest view https://registry.example.com/button.json

view 命令会显示:

  • Resource metadata (name, type, description)
  • Dependencies and registry dependencies
  • File contents that will be installed
  • CSS variables and Tailwind configuration
  • Required environment variables

搜索注册表

在注册表中搜索可用资源:

# Search a specific registry
npx shadcn@latest search @v0
 
# Search with query
npx shadcn@latest search @acme --query "auth"
 
# Search multiple registries
npx shadcn@latest search @v0 @acme @lib
 
# Limit results
npx shadcn@latest search @v0 --limit 10 --offset 20
 
# List all items (alias for search)
npx shadcn@latest list @acme

搜索结果包含:

  • Resource name and type
  • Description
  • Registry source

错误处理

注册表未配置

如果你引用了一个尚未配置的注册表:

pnpm dlx shadcn@latest add @non-existent/component

错误信息:

Unknown registry "@non-existent". Make sure it is defined in components.json as follows:
{
  "registries": {
    "@non-existent": "[URL_TO_REGISTRY]"
  }
}

缺少环境变量

如果必需的环境变量没有设置:

Registry "@private" requires the following environment variables:
 
  • REGISTRY_TOKEN
 
Set the required environment variables to your .env or .env.local file.

找不到资源

404 Not Found:

The item at https://registry.company.com/button.json was not found. It may not exist at the registry.

这通常意味着:

  • The resource name is misspelled
  • The resource doesn't exist in the registry
  • The registry URL pattern is incorrect

认证失败

401 Unauthorized:

You are not authorized to access the item at https://api.company.com/button.json
Check your authentication credentials and environment variables.

403 Forbidden:

Access forbidden for https://api.company.com/button.json
Verify your API key has the necessary permissions.

创建你自己的注册表

要让你的注册表兼容命名空间系统,你可以提供任何类型的资源 - 组件、库、工具、AI 提示、主题、配置,或者任何其他可共享的代码/内容:

  1. 实现注册表 item schema:你的注册表必须返回符合注册表 item schema 的 JSON。

  2. 支持 URL 模式:在 URL 模板中包含 {name},资源名会在这里插入。

  3. 定义资源类型:使用合适的 type 字段来标识你的资源(例如 registry:uiregistry:libregistry:airegistry:theme 等)。

  4. 处理认证(如需要):支持通过 headers 或查询参数认证。

  5. 记录你的命名空间:为用户提供清晰的配置说明:

components.json
{
  "registries": {
    "@your-registry": "https://your-domain.com/r/{name}.json"
  }
}

技术细节

解析器模式

命名空间解析器使用以下正则表达式模式:

namespace-parser.js
/^(@[a-zA-Z0-9](?:[a-zA-Z0-9-_]*[a-zA-Z0-9])?)\/(.+)$/

这可以确保命名空间格式有效,并正确提取组件名称。

解析流程

  1. 解析:从 @namespace/component 中提取命名空间和组件名称
  2. 查找:找到 @namespace 对应的注册表配置
  3. 构建 URL:用实际值替换占位符
  4. 设置 Headers:如果已配置,则应用认证 headers
  5. 获取:从解析后的 URL 拉取组件
  6. 校验:确保响应符合注册表 item schema
  7. 解析依赖:递归获取任何注册表依赖

跨注册表依赖

当组件依赖来自不同注册表的内容时,解析器会:

  1. 为每个注册表维护独立的认证上下文
  2. 从各自的来源解析每个依赖
  3. 基于目标路径对文件去重
  4. 合并来自所有来源的配置(tailwind、cssVars 等)

最佳实践

  1. 对 API key 和 token 等敏感数据使用环境变量
  2. 为注册表使用唯一且有描述性的命名空间名称
  3. 清楚记录认证要求,方便用户理解
  4. 提供正确的错误响应,并附带有帮助的信息
  5. 尽可能缓存注册表响应,提升性能
  6. 如果组件有多个主题,支持样式变体

故障排查

找不到资源

  • 确认注册表 URL 正确且可访问
  • 检查 URL 中是否包含 {name} 占位符
  • 确认资源确实存在于注册表中
  • 确认资源类型与注册表提供的内容一致

Authentication issues

  • Confirm environment variables are set correctly
  • Verify API keys/tokens are valid and not expired
  • Check that headers are being sent in the correct format

Dependency conflicts

  • Review resources with the same name from different registries
  • Use fully qualified names (@namespace/resource) to avoid ambiguity
  • Check for circular dependencies between registries
  • Ensure resource types are compatible when mixing registries