From b9314fb4555b8e3dfbfbcdb785accfc15e174360 Mon Sep 17 00:00:00 2001 From: Timeless0911 Date: Fri, 18 Sep 2026 17:40:50 +0800 Subject: [PATCH 1/3] docs: add release management guide --- website/docs/en/guide/advanced/_meta.json | 3 +- .../en/guide/advanced/release-management.mdx | 399 ++++++++++++++++++ website/docs/zh/guide/advanced/_meta.json | 3 +- .../zh/guide/advanced/release-management.mdx | 399 ++++++++++++++++++ 4 files changed, 802 insertions(+), 2 deletions(-) create mode 100644 website/docs/en/guide/advanced/release-management.mdx create mode 100644 website/docs/zh/guide/advanced/release-management.mdx diff --git a/website/docs/en/guide/advanced/_meta.json b/website/docs/en/guide/advanced/_meta.json index c5ffc611d..2c63232b2 100644 --- a/website/docs/en/guide/advanced/_meta.json +++ b/website/docs/en/guide/advanced/_meta.json @@ -13,5 +13,6 @@ "rspress", "storybook", "rstest", - "rsdoctor" + "rsdoctor", + "release-management" ] diff --git a/website/docs/en/guide/advanced/release-management.mdx b/website/docs/en/guide/advanced/release-management.mdx new file mode 100644 index 000000000..1a401086e --- /dev/null +++ b/website/docs/en/guide/advanced/release-management.mdx @@ -0,0 +1,399 @@ +--- +description: 'Learn about npm package version management and release practices for Rslib projects, including release preparation, versioning, build validation, npm publishing, and GitHub Actions integration.' +--- + +# Release management + +This chapter introduces npm package version management and release practices for Rslib projects. + +## Configure package.json + +Before publishing an npm package, first complete its basic `package.json` configuration. This includes confirming the package `name` and initial `version`, and configuring its exports, runtime requirements, and publishing scope. For example, an ESM package built with Rslib can use the following configuration: + +```json title="package.json" +{ + "name": "@example/lib", + "version": "0.0.0", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "types": "./dist/index.d.ts", + "files": ["dist"], + "engines": { + "node": ">=22.19.0" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} +``` + +Pay particular attention to the following fields: + +| Field | Description | +| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `exports`, `types` | Point the exports and type declarations to the actual build artifacts generated by Rslib. | +| `files` | Explicitly list the files to publish to avoid accidentally publishing tests, configuration, and other unrelated content. | +| `engines.node` | Declare the minimum supported Node.js version. | +| `publishConfig` | Scoped packages can set `access: "public"` for public publishing. This field can also override the registry used when publishing. | +| `dependencies`, `optionalDependencies`, `peerDependencies`, `devDependencies` | Rslib applies default external rules to third-party dependencies based on these fields. Declare dependencies according to their actual purpose; see [Default handling of third-party dependencies](/guide/advanced/third-party-deps#default-handling-of-third-party-dependencies) for details. | +| `sideEffects` | Declare package side effects correctly, including files that have import side effects such as CSS, polyfills, and global registrations. | + +Also make sure that the package does not set `private: true`. It is also recommended to add `description`, `license`, and `repository` so users can understand and locate the project on npm. + +## pnpm version management + +pnpm provides [versioning and publishing features](https://pnpm.io/versioning) for recording changes, updating package versions, generating changelogs, synchronizing dependency versions between workspace packages, and publishing npm packages. + +:::tip pnpm version requirement + +These versioning features require pnpm v11.13.0 or later. We recommend pinning the pnpm version with `packageManager` and declaring the minimum version with `engines.pnpm`: + +```json title="package.json" +{ + "packageManager": "pnpm@12.4.1", + "engines": { + "pnpm": ">=11.13.0" + } +} +``` + +::: + +The common versioning and publishing commands can be run locally or integrated into GitHub Actions and other CI platforms: + +| Command | Stage | Purpose | +| ------------------------------------------------ | ----------- | ------------------------------------------------------------------------- | +| [pnpm change](https://pnpm.io/cli/change) | Development | Record affected packages, version bump levels, and changes. | +| [pnpm change status](https://pnpm.io/cli/change) | Preparation | View pending change records and their version changes. | +| [pnpm version](https://pnpm.io/cli/version) | Preparation | Update package versions, including multiple workspace packages with `-r`. | +| [pnpm lane](https://pnpm.io/cli/lane) | Preparation | Manage prerelease channels such as Alpha, Beta, and RC. | +| [pnpm publish](https://pnpm.io/cli/publish) | Publishing | Publish packages directly to npm. | +| [pnpm stage publish](https://pnpm.io/cli/stage) | Publishing | Stage packages on npm for review and approval before release. | + +You can configure pnpm versioning behavior in `pnpm-workspace.yaml`. For example, configure a fixed version group to keep multiple packages at the same version: + +```yaml title="pnpm-workspace.yaml" +versioning: + fixed: + - ['@example/*'] +``` + +See the [pnpm versioning configuration](https://pnpm.io/settings/versioning) for all available options. + +## Release workflow + +A complete pnpm-based release process includes the following steps: + +1. [Record changes](#record-changes) +2. [Update versions](#update-versions) +3. [Maintain changelog](#maintain-changelog) +4. [Build and validate](#build-and-validate) +5. [Publish to npm](#publish-to-npm) + +### Record changes + +After completing changes that need to be released, run [pnpm change](https://pnpm.io/cli/change) to record the affected packages, version bump level, and change summary: + +```bash +pnpm change +``` + +pnpm generates a change record in the `.changeset/` directory based on the interactive options. The summary is used to generate the changelog during release, so it should clearly describe the user-facing behavior change. Commit the generated change record file together with the code. + +You can also record changes non-interactively by specifying the package name and options such as `--bump` and `--summary`: + +```bash +pnpm change --bump patch --summary "Example change" @example/core +``` + +Before preparing a release, view pending change records and their corresponding version changes: + +```bash +pnpm change status +``` + +### Update versions + +Run [pnpm version](https://pnpm.io/cli/version) to update versions when preparing a release: + +```bash +# Single-package repository +pnpm version patch + +# monorepo +pnpm version -r +``` + +When run in a Git repository, regular `pnpm version` creates a Git commit and an annotated tag for the version change. A single-package repository can inspect the generated commit and tag, then push them to the main branch for publishing. + +If you want to wrap single-package version updates in a script, add the following to `package.json`: + +```json title="package.json" +{ + "scripts": { + "bump": "pnpm version -m \"release: v%s\"" + } +} +``` + +In a monorepo project, run `pnpm version -r`. Recursive mode applies the change records and updates package versions, workspace dependencies, and changelogs, but does not create a commit or tag because one run may produce different versions for multiple packages. After checking the generated files, commit and push these changes to an agreed release branch, such as `release/v1.2.3`, and create a PR. Publish from that branch first, then merge the PR after the release is verified. + +During the version update process, choose an appropriate version type based on your needs. + +#### Stable and prerelease versions + +Stable versions are intended for all users. They do not include a prerelease identifier and normally use the `latest` dist-tag. + +Alpha, Beta, and RC versions are installable test versions released before a stable version. Use an npm dist-tag that matches the version suffix so that prereleases do not affect the default installation: + +| Version | npm dist-tag | +| --------------- | ------------ | +| `1.0.0-alpha.0` | `alpha` | +| `1.0.0-beta.0` | `beta` | +| `1.0.0-rc.0` | `rc` | +| `1.0.0` | `latest` | + +You can create a prerelease with [pnpm version](https://pnpm.io/cli/version): + +```bash +pnpm version prerelease --preid beta +``` + +If a group of workspace packages needs continuous prerelease releases, use [pnpm lane](https://pnpm.io/cli/lane) to maintain an independent prerelease channel: + +```bash +pnpm lane beta --filter '@example/*' +pnpm version -r + +# Move back to the main lane before releasing a stable version +pnpm lane main --filter '@example/*' +pnpm version -r +``` + +:::note + +Do not publish prereleases to `latest`, otherwise users installing the package normally may receive an unstable version. + +::: + +#### Snapshot packages + +Snapshot packages help validate a PR, branch, or commit without changing the stable version or changelog. For local validation, build and pack the package, then install the generated archive in a consumer project: + +```bash +# Run in the library project +pnpm build +pnpm pack + +# Run in the consumer project +pnpm add /path/to/package.tgz +``` + +To provide collaborators with an installable Snapshot package in a PR, use [pkg-pr-new](https://github.com/stackblitz-labs/pkg.pr.new#readme). It publishes packages to a separate npm-compatible service rather than the npm registry, so it does not increase the number of npm package versions or modify package metadata such as dist-tags. + +### Maintain changelog + +When you run `pnpm version -r`, pnpm generates changelogs from the summaries recorded by `pnpm change`. To maintain a `CHANGELOG.md` for each package in the repository, set [versioning.changelog.storage](https://pnpm.io/settings/versioning#versioningchangelogstorage) to `repository`: + +```yaml title="pnpm-workspace.yaml" +versioning: + changelog: + storage: repository +``` + +If the project uses GitHub release notes as the user-facing version record, you do not need to maintain an additional `CHANGELOG.md` in the repository. GitHub supports [automatically generated release notes](https://docs.github.com/repositories/releasing-projects-on-github/automatically-generated-release-notes), and you can add release highlights, migration instructions, and important notes to the generated content. + +### Build and validate + +After determining the version to publish, use the corresponding commit locally or in CI, install dependencies, and build: + +```bash +pnpm install --frozen-lockfile +pnpm build +``` + +Before publishing, run [pnpm publish --dry-run](https://pnpm.io/cli/publish) to check the files and package information that will be published: + +```bash +pnpm publish --dry-run +``` + +You can also check the package structure, exports, and type declarations to ensure that the final npm package can be resolved and installed correctly. Rslib supports the following Rsbuild plugins for these checks: + +- [rsbuild-plugin-publint](https://github.com/rstackjs/rsbuild-plugin-publint): Checks common issues in `package.json`, package structure, and exports. +- [rsbuild-plugin-arethetypeswrong](https://github.com/rstackjs/rsbuild-plugin-arethetypeswrong): Checks whether type declarations work correctly with different module resolution strategies. + +Install the plugins first, then add them to the `plugins` configuration. The plugins check release artifacts after the build completes. + +import { PackageManagerTabs } from '@theme'; + + + +The following configuration enables the checks with the `CI` environment variable set by most CI platforms, avoiding an impact on local build workflows. The checks run automatically when packages are built during the release workflow: + +```ts title="rslib.config.ts" +import { defineConfig } from '@rslib/core'; +import { pluginAreTheTypesWrong } from 'rsbuild-plugin-arethetypeswrong'; +import { pluginPublint } from 'rsbuild-plugin-publint'; + +export default defineConfig({ + dts: true, + plugins: [ + pluginPublint({ + enable: Boolean(process.env.CI), + }), + pluginAreTheTypesWrong({ + enable: Boolean(process.env.CI), + }), + ], +}); +``` + +You can also add syntax compatibility, bundle size, or installation tests based on the type of artifact. + +### Publish to npm + +There are two ways to publish npm packages: + +- **Staged publishing (recommended):** [pnpm stage publish](https://pnpm.io/cli/stage) separates uploading a package from making it publicly available. Staged versions are not resolved or installed by package managers, so maintainers can inspect the package before approving it on the npm website or with [pnpm stage approve](https://pnpm.io/cli/stage). This approach can reduce supply-chain risks if an npm token is stolen or a CI environment is compromised. + + ```bash + # Single-package repository + pnpm stage publish --tag latest --no-git-checks + + # monorepo + pnpm --filter './packages/*' -r stage publish --tag latest --no-git-checks + ``` + + Approve the staged packages on the npm website after checking them. + +- **Direct publishing:** If manual approval is not required, use [pnpm publish](https://pnpm.io/cli/publish) directly: + + ```bash + # Single-package repository + pnpm publish --tag latest --no-git-checks + + # monorepo + pnpm --filter './packages/*' -r publish --tag latest --no-git-checks + ``` + +## GitHub integration + +You can use GitHub Actions to build and publish the npm package. We recommend using npm [Trusted publishing](https://docs.npmjs.com/trusted-publishers/) for OIDC authentication to avoid storing long-lived npm tokens in CI. + +### Publish from a tag + +For a simple single-package repository, after updating the version, push the commit containing the version change to the main branch, then push the corresponding Git tag. The release workflow runs for the `v*` tag and can also be triggered manually: + +```yaml title=".github/workflows/release.yml" +name: Release + +on: + push: + tags: + - 'v*' + + workflow_dispatch: + +permissions: {} + +jobs: + publish: + runs-on: ubuntu-latest + environment: npm + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: 24 + + - name: Install pnpm + uses: pnpm/action-setup@v6 + with: + run_install: true + + - name: Build + run: pnpm run build + + - name: Publish to npm + run: pnpm stage publish --no-git-checks +``` + +### Publish from a release branch + +For a monorepo that publishes multiple packages together, use the release workflow to select an agreed release branch. After you use **Run workflow** to select the branch and npm dist-tag, the workflow builds that branch and recursively stages the packages for publishing: + +```yaml title=".github/workflows/release.yml" +name: Release + +on: + workflow_dispatch: + inputs: + npm_tag: + type: choice + description: 'Specify npm tag' + required: true + default: 'alpha' + options: + - alpha + - beta + - rc + - latest + branch: + description: 'Branch to release' + required: true + default: 'main' + +permissions: {} + +jobs: + release: + runs-on: ubuntu-latest + environment: npm + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 1 + ref: ${{ github.event.inputs.branch }} + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: 24 + + - name: Install pnpm + uses: pnpm/action-setup@v6 + with: + run_install: true + + - name: Build + run: pnpm run build + + - name: Publish to npm + run: | + pnpm --filter './packages/*' -r stage publish --tag ${{ github.event.inputs.npm_tag }} --no-git-checks +``` + +> The top-level `permissions: {}` disables the default `GITHUB_TOKEN` permissions. The publishing job only grants `contents: read` to check out the source and `id-token: write` for npm OIDC authentication. + +:::note + +When configuring Trusted publishing on npm, the repository and workflow filename must match the workflow. If you also configure an Environment for Trusted publishing, use the same name as the `npm` Environment in the examples above. + +::: diff --git a/website/docs/zh/guide/advanced/_meta.json b/website/docs/zh/guide/advanced/_meta.json index c5ffc611d..2c63232b2 100644 --- a/website/docs/zh/guide/advanced/_meta.json +++ b/website/docs/zh/guide/advanced/_meta.json @@ -13,5 +13,6 @@ "rspress", "storybook", "rstest", - "rsdoctor" + "rsdoctor", + "release-management" ] diff --git a/website/docs/zh/guide/advanced/release-management.mdx b/website/docs/zh/guide/advanced/release-management.mdx new file mode 100644 index 000000000..9d3ef0fde --- /dev/null +++ b/website/docs/zh/guide/advanced/release-management.mdx @@ -0,0 +1,399 @@ +--- +description: '介绍 Rslib 项目的 npm 包版本管理与发布实践,包括发布准备、版本管理、构建验证、npm 发布和 GitHub Actions 集成。' +--- + +# 版本管理与发布 + +本章介绍 Rslib 项目的 npm 包版本管理与发布实践。 + +## 配置 package.json \{#configure-packagejson} + +要将一个包发布到 npm,需要先在 `package.json` 中完成基础配置,包括确认 `name` 和初始 `version`,并明确导出配置、运行环境和发布范围等信息。例如,一个使用 Rslib 构建的 ESM 包可以配置为: + +```json title="package.json" +{ + "name": "@example/lib", + "version": "0.0.0", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "types": "./dist/index.d.ts", + "files": ["dist"], + "engines": { + "node": ">=22.19.0" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} +``` + +配置时需要重点关注以下字段: + +| 字段 | 说明 | +| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `exports`、`types` | 导出配置和类型声明应指向 Rslib 的实际构建产物。 | +| `files` | 明确需要发布的文件,避免将测试、配置等内容意外发布。 | +| `engines.node` | 声明包最低支持的 Node.js 版本。 | +| `publishConfig` | 带 scope 的包可以设置 `access: "public"` 公开发布,还可以通过该字段覆盖发布时使用的 registry 等配置。 | +| `dependencies`、`optionalDependencies`、`peerDependencies` 和 `devDependencies` | Rslib 会根据这些字段对三方依赖应用默认的 external 规则,因此需要按照依赖的实际用途正确声明,具体规则可以参考 [三方依赖的默认处理](/guide/advanced/third-party-deps#三方依赖的默认处理)。 | +| `sideEffects` | 声明包中的副作用,需要正确包含 CSS、polyfill 和全局注册等存在导入副作用的文件。 | + +此外,需要确保包没有设置 `private: true`,并建议补充 `description`、`license`、`repository` 等信息,方便用户在 npm 上了解和定位项目。 + +## pnpm 版本管理 \{#pnpm-version-management} + +pnpm 提供了 [发布管理功能](https://pnpm.io/versioning),支持记录变更、更新包版本、生成 changelog、同步更新 workspace 包之间的依赖版本,以及发布 npm 包。 + +:::tip pnpm 版本要求 + +相关版本管理功能需要 pnpm v11.13.0 或更高版本。建议通过 `packageManager` 固定使用的 pnpm 版本,并通过 `engines.pnpm` 声明最低版本: + +```json title="package.json" +{ + "packageManager": "pnpm@12.4.1", + "engines": { + "pnpm": ">=11.13.0" + } +} +``` + +::: + +常用的版本管理与发布命令既可以在本地运行,也可以集成到 GitHub Actions 或其他 CI 平台中: + +| 命令 | 阶段 | 用途 | +| ------------------------------------------------ | -------- | ----------------------------------------------------- | +| [pnpm change](https://pnpm.io/cli/change) | 开发 | 记录受影响的包、版本变更级别和 changelog 内容。 | +| [pnpm change status](https://pnpm.io/cli/change) | 发布准备 | 查看尚未应用的变更记录及其版本变化。 | +| [pnpm version](https://pnpm.io/cli/version) | 发布准备 | 更新包版本,支持通过 `-r` 更新 workspace 中的多个包。 | +| [pnpm lane](https://pnpm.io/cli/lane) | 发布准备 | 管理 Alpha、Beta 或 RC 等预发布通道。 | +| [pnpm publish](https://pnpm.io/cli/publish) | 发布 | 将包直接发布到 npm。 | +| [pnpm stage publish](https://pnpm.io/cli/stage) | 发布 | 将包暂存到 npm,审核并批准后再正式上线。 | + +pnpm 的版本管理行为可以通过 `pnpm-workspace.yaml` 进行配置。例如,可以配置固定版本组,让多个包始终保持相同版本: + +```yaml title="pnpm-workspace.yaml" +versioning: + fixed: + - ['@example/*'] +``` + +完整选项可以参考 [pnpm 版本管理配置](https://pnpm.io/settings/versioning)。 + +## 发布流程 \{#release-workflow} + +基于 pnpm 的完整发布流程包括以下步骤: + +1. [记录变更](#record-changes) +2. [版本更新](#update-versions) +3. [维护变更记录](#maintain-changelog) +4. [构建和验证](#build-and-validate) +5. [发布 npm 包](#publish-to-npm) + +### 记录变更 \{#record-changes} + +完成需要发布的改动后,可以运行 [pnpm change](https://pnpm.io/cli/change) 记录受影响的包、版本变更级别和变更摘要: + +```bash +pnpm change +``` + +pnpm 会根据交互式提示在 `.changeset/` 目录中生成变更记录。变更摘要会在发布时用于生成 changelog,因此应清晰描述面向用户的行为变化。生成的变更记录文件需要与代码一起提交。 + +你也可以通过包名以及 `--bump`、`--summary` 等参数,以非交互方式记录变更,例如: + +```bash +pnpm change --bump patch --summary "Example change" @example/core +``` + +准备发布前,可以查看尚未应用的变更记录及其对应的版本变化: + +```bash +pnpm change status +``` + +### 版本更新 \{#update-versions} + +准备发布时,可以运行 [pnpm version](https://pnpm.io/cli/version) 更新版本: + +```bash +# 单包仓库 +pnpm version patch + +# monorepo +pnpm version -r +``` + +在 Git 仓库中运行普通的 `pnpm version` 时,pnpm 会为版本变更创建 Git 提交和带有说明信息的版本标签(annotated tag)。单包仓库可以检查生成的提交和标签后,将它们推送到主分支进行发布。 + +如果希望将单包仓库的版本更新封装为脚本,可以在 `package.json` 中添加: + +```json title="package.json" +{ + "scripts": { + "bump": "pnpm version -m \"release: v%s\"" + } +} +``` + +在 monorepo 项目中,需要运行 `pnpm version -r`。递归模式会应用变更记录、更新各个包的版本、workspace 依赖和 changelog,但不会创建提交和版本标签,因为一次运行可能会生成多个不同的包版本。检查生成的文件后,通常可以将这些变更提交并推送到约定的发布分支(例如 `release/v1.2.3`),创建 PR,先从该分支发布,确认无误后再合并 PR。 + +在版本更新过程中,可以根据需要选择合适的版本类型。 + +#### 正式版本和预发布版本 \{#stable-and-prerelease-versions} + +正式版本面向所有用户,版本号不包含预发布标识,通常使用 `latest` dist-tag。 + +Alpha、Beta 和 RC 用于在正式版之前发布可安装的测试版本。发布时应使用与版本后缀对应的 npm dist-tag,避免影响默认安装: + +| 版本 | npm dist-tag | +| --------------- | ------------ | +| `1.0.0-alpha.0` | `alpha` | +| `1.0.0-beta.0` | `beta` | +| `1.0.0-rc.0` | `rc` | +| `1.0.0` | `latest` | + +可以通过 [pnpm version](https://pnpm.io/cli/version) 创建 prerelease: + +```bash +pnpm version prerelease --preid beta +``` + +如果需要为一组 workspace 包持续发布预发布版本,可以使用 [pnpm lane](https://pnpm.io/cli/lane) 维护独立的预发布通道: + +```bash +pnpm lane beta --filter '@example/*' +pnpm version -r + +# 发布正式版前移回 main lane +pnpm lane main --filter '@example/*' +pnpm version -r +``` + +:::note + +不要将 prerelease 发布到 `latest`,否则用户正常安装包时可能获取到尚未稳定的版本。 + +::: + +#### Snapshot 包 \{#snapshot-packages} + +Snapshot 包用于验证某个 PR、分支或提交,不需要修改正式版本或 changelog。如果只需要在本地验证,可以构建并打包,再到消费项目中安装生成的压缩包: + +```bash +# 在库项目中执行 +pnpm build +pnpm pack + +# 在消费项目中执行 +pnpm add /path/to/package.tgz +``` + +如果需要在 PR 中向协作者提供可安装的 Snapshot 包,可以使用 [pkg-pr-new](https://github.com/stackblitz-labs/pkg.pr.new#readme)。它会将包发布到 npm 兼容的独立服务,而不是 npm registry,因此不会增加 npm 包的版本数量,也不会修改 dist-tag 等包元数据。 + +### 维护变更记录 \{#maintain-changelog} + +运行 `pnpm version -r` 时,pnpm 会根据 `pnpm change` 记录的变更摘要生成 changelog。如果希望在仓库中维护每个包的 `CHANGELOG.md`,可以将 [versioning.changelog.storage](https://pnpm.io/settings/versioning#versioningchangelogstorage) 设置为 `repository`: + +```yaml title="pnpm-workspace.yaml" +versioning: + changelog: + storage: repository +``` + +如果项目使用 GitHub release notes 作为面向用户的版本记录,则不必在仓库中额外维护 `CHANGELOG.md`。GitHub 支持 [自动生成 release notes](https://docs.github.com/repositories/releasing-projects-on-github/automatically-generated-release-notes),也可以在自动生成的内容中补充版本亮点、迁移说明和重要注意事项。 + +### 构建和验证 \{#build-and-validate} + +确定要发布的版本后,在本地或 CI 中使用对应的提交,安装依赖并构建: + +```bash +pnpm install --frozen-lockfile +pnpm build +``` + +发布前,可以先运行 [pnpm publish --dry-run](https://pnpm.io/cli/publish),检查将要发布的文件和包信息: + +```bash +pnpm publish --dry-run +``` + +我们还可以进一步对包结构、导出配置和类型声明进行检查,确保最终的 npm 包能够被正确解析和安装。Rslib 支持使用以下 Rsbuild 插件完成检查: + +- [rsbuild-plugin-publint](https://github.com/rstackjs/rsbuild-plugin-publint):检查 `package.json`、包结构和导出配置等常见问题。 +- [rsbuild-plugin-arethetypeswrong](https://github.com/rstackjs/rsbuild-plugin-arethetypeswrong):检查类型声明能否在不同的模块解析方式下正确使用。 + +使用时,先安装插件,再将它们添加到 `plugins` 配置中。插件会在构建完成后检查发布产物。 + +import { PackageManagerTabs } from '@theme'; + + + +下面的配置通过大多数 CI 平台默认设置的 `CI` 环境变量启用检查,避免影响本地构建流程。在发布流程中构建包时会自动执行这些检查: + +```ts title="rslib.config.ts" +import { defineConfig } from '@rslib/core'; +import { pluginAreTheTypesWrong } from 'rsbuild-plugin-arethetypeswrong'; +import { pluginPublint } from 'rsbuild-plugin-publint'; + +export default defineConfig({ + dts: true, + plugins: [ + pluginPublint({ + enable: Boolean(process.env.CI), + }), + pluginAreTheTypesWrong({ + enable: Boolean(process.env.CI), + }), + ], +}); +``` + +此外,项目还可以根据产物类型增加语法兼容性、体积或实际安装测试。 + +### 发布 npm 包 \{#publish-to-npm} + +发布 npm 包有以下两种方式: + +- **暂存发布(推荐):** [pnpm stage publish](https://pnpm.io/cli/stage) 将上传包与正式上线拆分为两个步骤。暂存版本不会被包管理器解析或安装,维护者可以先检查包内容,再在 npm 网站或通过 [pnpm stage approve](https://pnpm.io/cli/stage) 二次确认后正式上线。这种方式可以降低 npm token 被窃取或 CI 环境遭到入侵后,恶意版本被直接发布的供应链风险。 + + ```bash + # 单包仓库 + pnpm stage publish --tag latest --no-git-checks + + # monorepo + pnpm --filter './packages/*' -r stage publish --tag latest --no-git-checks + ``` + + 检查无误后,在 npm 网站批准暂存版本。 + +- **直接发布:** 如果不需要人工确认,可以直接使用 [pnpm publish](https://pnpm.io/cli/publish): + + ```bash + # 单包仓库 + pnpm publish --tag latest --no-git-checks + + # monorepo + pnpm --filter './packages/*' -r publish --tag latest --no-git-checks + ``` + +## GitHub 集成 \{#github-integration} + +你可以通过 GitHub Actions 构建和发布 npm 包。发布时,建议使用 npm [Trusted publishing](https://docs.npmjs.com/trusted-publishers/) 进行 OIDC 身份验证,避免在 CI 中保存长期有效的 npm token。 + +### 通过 tag 发布 \{#publish-from-a-tag} + +对于简单的单包仓库,完成版本更新后,将包含版本变更的提交推送到主分支,并推送对应的 Git tag。发布工作流会根据 `v*` tag 触发,也支持手动运行: + +```yaml title=".github/workflows/release.yml" +name: Release + +on: + push: + tags: + - 'v*' + + workflow_dispatch: + +permissions: {} + +jobs: + publish: + runs-on: ubuntu-latest + environment: npm + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: 24 + + - name: Install pnpm + uses: pnpm/action-setup@v6 + with: + run_install: true + + - name: Build + run: pnpm run build + + - name: Publish to npm + run: pnpm stage publish --no-git-checks +``` + +### 通过发布分支发布 \{#publish-from-a-release-branch} + +对于需要同时发布多个包的 monorepo,可以通过发布工作流选择约定的发布分支。使用 **Run workflow** 选择要发布的分支和 npm dist-tag 后,工作流会构建该分支的代码,并对需要发布的包递归执行暂存发布: + +```yaml title=".github/workflows/release.yml" +name: Release + +on: + workflow_dispatch: + inputs: + npm_tag: + type: choice + description: 'Specify npm tag' + required: true + default: 'alpha' + options: + - alpha + - beta + - rc + - latest + branch: + description: 'Branch to release' + required: true + default: 'main' + +permissions: {} + +jobs: + release: + runs-on: ubuntu-latest + environment: npm + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 1 + ref: ${{ github.event.inputs.branch }} + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version: 24 + + - name: Install pnpm + uses: pnpm/action-setup@v6 + with: + run_install: true + + - name: Build + run: pnpm run build + + - name: Publish to npm + run: | + pnpm --filter './packages/*' -r stage publish --tag ${{ github.event.inputs.npm_tag }} --no-git-checks +``` + +> 顶层的 `permissions: {}` 会关闭 `GITHUB_TOKEN` 的默认权限。发布任务仅授予 `contents: read` 用于检出源码,以及 `id-token: write` 用于通过 OIDC 向 npm 证明身份。 + +:::note + +在 npm 配置 Trusted publishing 时,仓库和工作流文件名必须与工作流一致。上面的示例使用名为 `npm` 的 GitHub Environment,如果在 Trusted publishing 中也配置了 Environment,需要使用相同的名称。 + +::: From 63e1819f3c86748a98eb98033b9ed5fc47302746 Mon Sep 17 00:00:00 2001 From: Timeless0911 Date: Fri, 18 Sep 2026 18:49:00 +0800 Subject: [PATCH 2/3] docs: refine release management guide --- .../en/guide/advanced/release-management.mdx | 28 ++++++++++++----- .../zh/guide/advanced/release-management.mdx | 30 ++++++++++++++----- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/website/docs/en/guide/advanced/release-management.mdx b/website/docs/en/guide/advanced/release-management.mdx index 1a401086e..ae90a93a3 100644 --- a/website/docs/en/guide/advanced/release-management.mdx +++ b/website/docs/en/guide/advanced/release-management.mdx @@ -118,6 +118,8 @@ Before preparing a release, view pending change records and their corresponding pnpm change status ``` +Single-package repositories can skip this step when change intents are not needed and specify the version type directly when updating versions. + ### Update versions Run [pnpm version](https://pnpm.io/cli/version) to update versions when preparing a release: @@ -221,7 +223,11 @@ pnpm build Before publishing, run [pnpm publish --dry-run](https://pnpm.io/cli/publish) to check the files and package information that will be published: ```bash +# Single-package repository pnpm publish --dry-run + +# monorepo +pnpm --filter './packages/*' -r publish --dry-run ``` You can also check the package structure, exports, and type declarations to ensure that the final npm package can be resolved and installed correctly. Rslib supports the following Rsbuild plugins for these checks: @@ -283,6 +289,8 @@ There are two ways to publish npm packages: pnpm --filter './packages/*' -r publish --tag latest --no-git-checks ``` +For prereleases, replace `latest` with the corresponding `alpha`, `beta`, or `rc` dist-tag. + ## GitHub integration You can use GitHub Actions to build and publish the npm package. We recommend using npm [Trusted publishing](https://docs.npmjs.com/trusted-publishers/) for OIDC authentication to avoid storing long-lived npm tokens in CI. @@ -312,15 +320,15 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Setup Node.js - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 - name: Install pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 with: run_install: true @@ -328,9 +336,15 @@ jobs: run: pnpm run build - name: Publish to npm - run: pnpm stage publish --no-git-checks + run: pnpm stage publish --tag latest --no-git-checks ``` +:::note + +To publish an `alpha`, `beta`, or other prerelease version, replace `latest` with the corresponding npm dist-tag. + +::: + ### Publish from a release branch For a monorepo that publishes multiple packages together, use the release workflow to select an agreed release branch. After you use **Run workflow** to select the branch and npm dist-tag, the workflow builds that branch and recursively stages the packages for publishing: @@ -367,18 +381,18 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 1 ref: ${{ github.event.inputs.branch }} - name: Setup Node.js - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 - name: Install pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 with: run_install: true diff --git a/website/docs/zh/guide/advanced/release-management.mdx b/website/docs/zh/guide/advanced/release-management.mdx index 9d3ef0fde..ba69732c5 100644 --- a/website/docs/zh/guide/advanced/release-management.mdx +++ b/website/docs/zh/guide/advanced/release-management.mdx @@ -6,7 +6,7 @@ description: '介绍 Rslib 项目的 npm 包版本管理与发布实践,包括 本章介绍 Rslib 项目的 npm 包版本管理与发布实践。 -## 配置 package.json \{#configure-packagejson} +## 配置 package.json \{#configure-package-json} 要将一个包发布到 npm,需要先在 `package.json` 中完成基础配置,包括确认 `name` 和初始 `version`,并明确导出配置、运行环境和发布范围等信息。例如,一个使用 Rslib 构建的 ESM 包可以配置为: @@ -118,6 +118,8 @@ pnpm change --bump patch --summary "Example change" @example/core pnpm change status ``` +单包仓库如果不需要记录变更意图,可以跳过此步骤,直接在版本更新时指定版本类型。 + ### 版本更新 \{#update-versions} 准备发布时,可以运行 [pnpm version](https://pnpm.io/cli/version) 更新版本: @@ -221,7 +223,11 @@ pnpm build 发布前,可以先运行 [pnpm publish --dry-run](https://pnpm.io/cli/publish),检查将要发布的文件和包信息: ```bash +# 单包仓库 pnpm publish --dry-run + +# monorepo +pnpm --filter './packages/*' -r publish --dry-run ``` 我们还可以进一步对包结构、导出配置和类型声明进行检查,确保最终的 npm 包能够被正确解析和安装。Rslib 支持使用以下 Rsbuild 插件完成检查: @@ -283,6 +289,8 @@ export default defineConfig({ pnpm --filter './packages/*' -r publish --tag latest --no-git-checks ``` +发布 prerelease 时,将 `latest` 替换为对应的 `alpha`、`beta` 或 `rc` dist-tag。 + ## GitHub 集成 \{#github-integration} 你可以通过 GitHub Actions 构建和发布 npm 包。发布时,建议使用 npm [Trusted publishing](https://docs.npmjs.com/trusted-publishers/) 进行 OIDC 身份验证,避免在 CI 中保存长期有效的 npm token。 @@ -312,15 +320,15 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Setup Node.js - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 - name: Install pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 with: run_install: true @@ -328,9 +336,15 @@ jobs: run: pnpm run build - name: Publish to npm - run: pnpm stage publish --no-git-checks + run: pnpm stage publish --tag latest --no-git-checks ``` +:::note + +发布 `alpha`、`beta` 等 prerelease 版本时,请将 `latest` 替换为对应的 npm dist-tag。 + +::: + ### 通过发布分支发布 \{#publish-from-a-release-branch} 对于需要同时发布多个包的 monorepo,可以通过发布工作流选择约定的发布分支。使用 **Run workflow** 选择要发布的分支和 npm dist-tag 后,工作流会构建该分支的代码,并对需要发布的包递归执行暂存发布: @@ -367,18 +381,18 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 1 ref: ${{ github.event.inputs.branch }} - name: Setup Node.js - uses: actions/setup-node@v7 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24 - name: Install pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 with: run_install: true From 075a3ff503a4cb0a8364b6abdce891a6a6b337ee Mon Sep 17 00:00:00 2001 From: Timeless0911 Date: Fri, 18 Sep 2026 18:57:19 +0800 Subject: [PATCH 3/3] docs: pin checkout version annotation --- website/docs/en/guide/advanced/release-management.mdx | 4 ++-- website/docs/zh/guide/advanced/release-management.mdx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/en/guide/advanced/release-management.mdx b/website/docs/en/guide/advanced/release-management.mdx index ae90a93a3..0e2f2559c 100644 --- a/website/docs/en/guide/advanced/release-management.mdx +++ b/website/docs/en/guide/advanced/release-management.mdx @@ -320,7 +320,7 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 @@ -381,7 +381,7 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 1 ref: ${{ github.event.inputs.branch }} diff --git a/website/docs/zh/guide/advanced/release-management.mdx b/website/docs/zh/guide/advanced/release-management.mdx index ba69732c5..3b41e76bf 100644 --- a/website/docs/zh/guide/advanced/release-management.mdx +++ b/website/docs/zh/guide/advanced/release-management.mdx @@ -320,7 +320,7 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 @@ -381,7 +381,7 @@ jobs: id-token: write steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 1 ref: ${{ github.event.inputs.branch }}