精通 Salesforce 2GP:第二代打包开发人员指南

背景与应用场景

作为一名 Salesforce 开发人员,我的日常工作不仅仅是编写 Apex 代码、创建 LWC 组件,更重要的是如何高效、可靠地管理和分发我们构建的应用程序。在 Salesforce 的生态系统中,打包 (Packaging) 是实现此目标的核心机制。长期以来,第一代打包 (First-Generation Packaging, 1GP) 是我们的主要选择,但它存在一些固有的挑战:它与特定的打包组织 (Packaging Org) 紧密耦合,版本控制和源代码管理流程繁琐,并且难以融入现代的持续集成/持续交付 (CI/CD) 管道。

为了解决这些痛点,Salesforce 推出了 Second-Generation Packaging (2GP)。2GP 是一种全新的应用程序分发模型,它基于 Salesforce DX (Developer Experience) 工具集,并以源代码驱动 (source-driven) 的开发理念为核心。它彻底改变了我们开发、测试和部署 Salesforce 应用的方式。

2GP 的主要应用场景包括:

  • ISV (独立软件供应商) 应用开发: 对于在 AppExchange 上发布应用的合作伙伴来说,2GP 提供了更强大的版本控制、依赖管理和自动化能力,极大地提升了发布流程的可靠性和效率。
  • 企业内部应用模块化: 大型企业通常拥有多个复杂的 Salesforce 组织。通过 2GP,企业可以将庞大的单体应用拆分为多个独立的、可重用的功能模块(包)。这不仅降低了代码的复杂性,还使得不同团队可以并行开发和独立部署,实现了真正的模块化和敏捷开发。
  • CI/CD 自动化: 2GP 的所有操作都可以通过 Salesforce CLI (SFDX CLI) 完成,这使得将打包、测试和部署流程完全集成到自动化管道(如 Jenkins, GitHub Actions, Azure DevOps)中变得轻而易举。

从开发人员的角度来看,2GP 意味着我们可以像对待其他现代软件项目一样对待 Salesforce 开发:以 Git 等版本控制系统为“单一事实来源”,使用临时性的 Scratch Orgs 进行干净的开发和测试,并通过命令行精确控制每一个版本,最终实现稳定、可预测的交付。


原理说明

2GP 的核心是源代码驱动Dev Hub。与 1GP 依赖于一个长期存在的“黄金”打包组织不同,2GP 的权威来源是您的版本控制系统(例如 Git)中的元数据。整个生命周期都围绕着 Salesforce DX 项目和 Dev Hub 组织展开。

1. Dev Hub

Dev Hub 是管理 2GP 包和 Scratch Orgs 的中央枢纽。您必须在您的生产组织或业务组织中启用 Dev Hub 功能。Dev Hub 本身不包含任何包的元数据,但它会跟踪您创建的所有包、包的版本以及与之关联的命名空间 (Namespace)。它充当着一个注册中心和控制台的角色。

2. Salesforce DX 项目

一个标准的 Salesforce DX 项目是 2GP 的基础。项目根目录下的 sfdx-project.json 文件是至关重要的配置文件。开发人员在这个文件中定义一个或多个包,声明它们的依赖关系,并指定其他配置信息。

3. 包 (Package) 和版本 (Package Version)

在 2GP 中,我们首先创建一个“包”的记录,这个包可以看作是一个容器或命名空间。然后,我们基于项目中的特定代码快照(通常是一个 Git commit)来创建“包的版本”。每个版本都是一个不可变的、可独立安装的工件。版本号遵循 Major.Minor.Patch.Build 的格式,例如 1.2.0.5

4. 包的类型

2GP 支持两种主要类型的包:

  • Managed Packages (受管包): 主要为 ISV 设计,用于在 AppExchange 上分发。受管包可以保护知识产权(例如 Apex 代码是隐藏的),支持升级,并且可以进行安全审查。
  • Unlocked Packages (非锁定包): 主要为企业客户设计,用于在内部不同组织之间分发元数据。非锁定包的元数据在安装后是可见且可修改的,非常适合企业内部的模块化开发和部署。

5. 开发流程

典型的 2GP 开发流程如下:

  1. 项目设置: 在本地创建一个 Salesforce DX 项目,并使用版本控制系统(如 Git)进行管理。
  2. 开发与测试: 开发人员为每个功能或修复创建一个新的 Scratch Org。Scratch Org 是一个临时的、功能齐全的 Salesforce 组织,其元数据可以从本地源代码中推送。这确保了每次开发都在一个干净的环境中进行。
  3. 创建版本: 当一个功能开发完成并通过测试后,开发人员使用 SFDX CLI 命令从代码库的当前状态创建一个新的包版本(通常是 beta 版本)。这个过程是异步的,由 Dev Hub 在后台处理。
  4. 集成测试: 将新创建的 beta 版本安装到一个新的 Scratch Org 或沙箱中,进行回归测试和集成测试。
  5. 发布: 如果测试通过,使用 SFDX CLI 命令将 beta 版本“提升”为发布版 (Released)。发布版的包版本是不可变的,可以安装到生产组织中。

这个流程将 Salesforce 开发从基于组织的模式转变为基于工件的模式,更加符合现代 DevOps 实践。


示例代码

以下示例代码均来自 Salesforce 官方文档,展示了使用 Salesforce CLI 管理 2GP 生命周期的核心命令。这些命令通常在 CI/CD 脚本中执行。

1. 在 sfdx-project.json 中定义包

在执行任何打包命令之前,您必须在项目中定义您的包。以下是一个 sfdx-project.json 文件的示例,它定义了一个名为 "dreamhouse" 的非锁定包。

{
   "packageDirectories": [
      {
         "path": "force-app",
         "default": true,
         "package": "dreamhouse",
         "versionName": "ver 0.1",
         "versionNumber": "0.1.0.NEXT"
      }
   ],
   "namespace": "",
   "sfdcLoginUrl": "https://login.salesforce.com",
   "sourceApiVersion": "58.0",
   "packageAliases": {
      "dreamhouse": "0Ho...oA0"
   }
}

2. 创建一个包

此命令会在 Dev Hub 中注册一个新的包。您只需要为每个包执行一次此操作。-v 参数指向您的 Dev Hub 组织别名。

// 创建一个名为 "dreamhouse" 的非锁定包
// --name: 包的名称
// --packagetype: 包的类型 (Managed 或 Unlocked)
// --path: 包含包元数据的目录
// --targetdevhubusername: 你的 Dev Hub 组织的别名
sfdx force:package:create --name "dreamhouse" --packagetype Unlocked --path force-app --targetdevhubusername MyDevHub

成功后,CLI 会返回一个包 ID (以 0Ho 开头),您应该将它添加到 sfdx-project.jsonpackageAliases 部分。

3. 创建一个包版本

这是最常用的命令之一。它会获取指定路径下的元数据,并创建一个不可变的包版本。

// 基于 "dreamhouse" 包创建一个新的 beta 版本
// --package: 要创建版本的包的别名或 ID
// --path: 包含元数据的目录
// --installationkey: 为此版本设置安装密码,保护您的包
// --wait: 指定等待版本创建完成的时间(分钟)
// --codecoverage: 要求 Apex 代码覆盖率(对于受管包是强制的)
sfdx force:package:version:create --package "dreamhouse" --path force-app --installationkey "YourInstallKey" --wait 10 --codecoverage

此命令是异步的。执行后,它会返回一个包版本创建请求的 ID。您可以使用 force:package:version:create:report 命令来检查其状态。

4. 提升包版本为发布版

当一个 beta 版本经过充分测试后,您可以将其提升为发布版,以便安装到生产组织。

// 将指定的包版本提升为发布状态
// --package: 要提升的包版本的别名或 ID (例如 dreamhouse@0.1.0-5)
// --targetdevhubusername: 你的 Dev Hub 组织的别名
sfdx force:package:version:promote --package "dreamhouse@0.1.0-5" --targetdevhubusername MyDevHub

5. 安装包版本到目标组织

使用此命令将指定的包版本安装到任何组织(Scratch Org、沙箱或生产组织)。

// 将包版本安装到目标组织
// --targetusername: 目标组织的别名
// --package: 要安装的包版本的别名或 ID
// --installationkey: 安装时所需的密码
// --wait: 等待安装完成的时间
sfdx force:package:install --targetusername MyTestOrg --package "dreamhouse@0.1.0-5" --installationkey "YourInstallKey" --wait 10

注意事项

权限和设置

  • Dev Hub 启用: 必须在您的组织中启用 Dev Hub 功能。这通常在生产组织中完成。
  • 用户权限: 执行操作的用户必须具有适当的权限。关键权限是“Create and Update Second-Generation Packages”。
  • 命名空间注册: 如果您要创建受管包,必须首先在您的 Dev Hub 组织中注册一个全局唯一的命名空间。这个命名空间会与您的 Dev Hub 永久关联。

API 限制和性能

  • 异步操作: 创建包版本是一个异步过程,可能需要几分钟到半小时不等,具体取决于包的大小和复杂性。不要在脚本中假设它会立即完成,始终使用报告命令来轮询状态。
  • Dev Hub API 限制: 所有 SFDX CLI 命令在后台都会消耗 API 调用。在频繁构建版本的 CI/CD 环境中,需要监控您的 Dev Hub 组织的 API 使用情况。可以使用 sfdx force:limits:api:display -u MyDevHub 命令进行检查。
  • 版本创建限制: Salesforce 对每天可以创建的包版本数量有限制,请查阅官方文档了解最新的限制信息。

错误处理

  • 版本创建失败: 版本创建失败的常见原因包括:Apex 测试失败、代码覆盖率不足、元数据依赖问题或无效的元数据。使用 sfdx force:package:version:create:report --packagecreaterequestid 来获取详细的错误日志。
  • 依赖管理: 2GP 允许在 sfdx-project.json 中定义包之间的依赖关系。如果依赖关系链不正确或存在循环依赖,版本创建将会失败。请仔细规划您的包依赖架构。
  • 可升级性: 对于受管包,一旦一个组件被标记为 global 并发布,您就无法轻易地删除它或更改其签名。在发布之前,请仔细考虑组件的 API 设计和长期可维护性。

总结与最佳实践

Second-Generation Packaging (2GP) 是 Salesforce 平台开发和部署的未来。它通过拥抱源代码驱动的理念和与 Salesforce DX 工具链的深度集成,为开发人员提供了前所未有的灵活性、可控性和自动化能力。

作为一名 Salesforce 开发人员,采纳 2GP 的最佳实践至关重要:

  1. 拥抱版本控制: 将 Git 等版本控制系统作为您唯一的“事实来源”。所有更改都应通过代码提交和拉取请求进行跟踪。
  2. 保持包的模块化和内聚性: 遵循“高内聚,低耦合”的原则。将您的应用程序拆分为功能独立的、小而精的包。这不仅简化了开发,也使得依赖管理和部署更加灵活。
  3. 自动化一切: 建立一个完整的 CI/CD 管道。自动化包版本的创建、在 Scratch Org 中的单元测试和集成测试、以及最终的部署。这将极大地减少人为错误并提高交付速度。
  4. 制定清晰的版本控制策略: 采用语义化版本控制 (Semantic Versioning) 来管理您的包版本号 (Major.Minor.Patch)。这使得依赖管理和向后兼容性变得清晰可预测。
  5. 充分利用 Scratch Orgs: 为每个开发任务(功能、修复)使用一个新的、干净的 Scratch Org。这可以避免环境差异带来的“在我机器上可以运行”的问题,并确保您的包在干净的环境中是可部署和可测试的。

从 1GP 迁移到 2GP 可能需要一些前期的学习和投入,但它所带来的在开发效率、代码质量和部署可靠性方面的长期收益是无与伦比的。对于任何希望在 Salesforce 平台上构建复杂、可扩展和可维护应用程序的开发团队来说,掌握 2GP 都是一项必备技能。

评论

此博客中的热门博文

Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)

Salesforce 登录取证:深入解析用户访问监控与安全

Salesforce Data Loader 全方位指南:数据迁移与管理的最佳实践