mcpField
P
publish-npm-package

publish-npm-package

github.com/yigitkonur云与 DevOps13135 次安装2 天前更新
代码仓库

关于 publish-npm-package

用于配置和排查通过 GitHub Actions 发布 npm 包的技能,指导开发者处理认证、版本管理、工作流选择、验证与恢复,并将详细模板放在独立参考文档中。

主要功能

  1. 01选择 OIDC 或令牌认证
  2. 02确定发布版本管理方式
  3. 03查找对应工作流模板
  4. 04检查包与仓库前置条件
  5. 05验证构建和包内容
  6. 06诊断发布故障

适用场景

  1. 01通过 GitHub Actions 自动发布 npm 包
  2. 02为包发布选择认证方式
  3. 03为单包或 monorepo 设置版本管理
  4. 04排查 CI 中的 npm 发布错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yigitkonur/skills-by-yigitkonur --skill publish-npm-package

安装后在 Claude Code 中输入/publish-npm-package确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
common-issues.md
monorepo-publishing.md
package-config.md
supply-chain.md
references/auth/
granular-tokens.md
oidc-trusted-publishing.md
references/versioning/
changesets.md
release-please.md
semantic-release.md
references/workflows/
oidc-workflows.md
token-workflows.md
scripts/
check-npm-auth.md
check-npm-auth.sh
check-package-json.md
check-package-json.mjs
dry-run-publish.md
dry-run-publish.sh

详细介绍

发布 npm 包

通过 GitHub Actions 设置 npmjs 发布,打造完整且内部一致的发布流程:认证、版本管理、包管理器安装、工作流触发、来源证明、验证和恢复。决策与路由规则位于此处;完整的 YAML 和工具深入介绍位于 references/。

适用场景

如果请求属于以下情况,请使用此技能:

  • “将此包发布到 npm”、“设置 npm 发布”、“自动化 npm 发布”
  • “从 GitHub Actions 发布到 npm”、“npm 发布工作流”、“npm CI/CD”
  • “可信发布”、“npm 的 OIDC”、“NPM_TOKEN 来源证明”、“id-token: write”
  • “semantic-release”、“changesets”、“release-please”、“自动更新版本号”
  • “首次发布新包”、“初始化 npm 包”、“将 GitHub 仓库关联到 npm”
  • “为什么我的 npm 发布失败”、“CI 中的 EOTP / ENEEDAUTH / E403”、“Actions 中的 npm whoami”

应触发此技能的 package.json / 仓库信号:

  • "name" 字段以及 "version",并且 repository.url 指向 GitHub
  • .github/workflows/*.yml 中包含 npm publish、setup-node、id-token: write 或 NPM_TOKEN
  • .npmrc 中包含 //registry.npmjs.org/:_authToken 或 ${NODE_AUTH_TOKEN}
  • 存在 .releaserc*、release.config.js、.changeset/ 或 .release-please-*.json
  • 带作用域的名称(@scope/name)以及 publishConfig.access 的相关决策

以下情况不要使用此技能:

  • 将应用/服务部署到运行平台(Railway、Vercel、Fly)——使用对应的平台技能(例如 run-railway)
  • 编写包自身的运行时代码、SDK 内部实现或 API——使用相关的 build-* 技能
  • 发布到非 npm 注册表(Docker Hub、GHCR、PyPI、crates.io),且不涉及 npm
  • 唯一需求只是询问应运行哪个 npm / 包管理器命令,且不涉及 CI 或发布自动化

先决定认证方式,再决定版本管理,最后选择工作流模板

务必遵循此顺序。跳过步骤会导致发布自动化配置不完整。

  1. 对仓库进行分类(见下表)。
  2. 选择认证方式:OIDC 可信发布,或令牌(NPM_TOKEN → NODE_AUTH_TOKEN)。
  3. 选择版本管理方式:semantic-release、changesets、release-please 或手动管理。
  4. 路由到 references/workflows/ 中的对应工作流模板。
  5. 检查包/仓库前置条件以及锁文件/包管理器。
  6. 使用 npm pack --dry-run、CI 中的构建/测试以及工具专用的 dry run 进行验证。
  7. 如果仓库正在迁移或已有故障,请跳转到文末的恢复路由。
先对仓库进行分类

回答以下问题并记录答案——后续所有决策都取决于这些答案:

  1. 包是公开还是私有?
  2. 是否使用 GitHub Actions 和 GitHub 托管的运行器(而非自托管运行器 / GHES / 非 GitHub CI)?
  3. 是单包还是 monorepo / 工作区?
  4. 是否实际使用 Conventional Commits(大多数有意义的提交是否采用 type: description 格式)?
  5. 是在每次可发布的合并后自动发布,还是由人工审核 Release/Version PR?
  6. 是全新项目(从未发布),还是已发布过且已有标签/版本?
  7. 目标是否确实是 npmjs.org?

根据 package.json 和工作区清单 → 现有工作流 → git 远程地址/标签 → npm 注册表状态推断答案。如果仍不明确,请停止并询问,不要猜测。

决策矩阵
公开?使用 GitHub 托管的运行器?单包/MonorepoConventional Commits?发布关卡认证方式版本管理
是是单包是自动OIDCsemantic-release
是是单包是人工审核OIDCrelease-please
是是单包否人工审核OIDCchangesets
是是单包否(全新项目,将采用 Conventional Commits)人工审核OIDCrelease-please
是是Monorepo任意任意OIDCchangesets(默认)
否任意任意任意任意令牌(任意)
任意否(自托管/GHES)任意任意任意令牌(任意)

认证路径——务必分开使用

路径适用场景要求发布来源证明
OIDC 可信发布公共软件包、公共仓库、GitHub 托管的运行器、已在 npm 上关联的软件包无需 npm 令牌、id-token: write、contents: read、npm CLI 11.5.1+、Node 22.14.0+npm publish --access public自动适用于符合条件的公共软件包——不要添加 --provenance
令牌 + 来源证明必须使用令牌认证、需要公共来源证明NODE_AUTH_TOKEN、id-token: write、云运行器、npm CLI 9.5.0+npm publish --provenance --access public显式标志、NPM_CONFIG_PROVENANCE=true 或工具配置
仅令牌私有软件包、自托管运行器、GHES、私有注册表、引导发布NODE_AUTH_TOKEN;无需 id-tokennpm publish --access public无

认证规则:

  • 支持时,默认使用 OIDC。可信发布意味着无需任何 npm 密钥——如果发布步骤设置了 NODE_AUTH_TOKEN 或 NPM_TOKEN,那就是令牌认证,而非可信发布,即使设置了 id-token: write 也一样。
  • OIDC 要求软件包已存在于 npm 上。全新软件包的首次发布必须先使用细粒度令牌进行引导,然后在 npm 上关联仓库,再切换到 OIDC。
  • OIDC 不适用于自托管运行器。在这种情况下,请使用细粒度令牌。
  • 将 secrets.NPM_TOKEN 作为 NODE_AUTH_TOKEN 提供。不要在 CI 中运行 npm login。新项目应避免使用经典自动化令牌。
  • 每个仓库或工作流入口使用一个细粒度令牌;按计划轮换。

查看完整的认证路径说明:

  • references/auth/oidc-trusted-publishing.md — OIDC 引导、仓库关联、来源证明默认设置
  • references/auth/granular-tokens.md — 细粒度令牌创建、作用域设置、轮换、密钥接入

本地发布与 CI 发布——确认当前使用的模式

混淆两者是导致 EOTP / ENEEDAUTH 错误的头号原因。

防护措施: 只有当 .npmrc 包含 ${NODE_AUTH_TOKEN} 时,裸环境变量 NODE_AUTH_TOKEN 才有效。在 GitHub Actions 中,设置 registry-url 后,actions/setup-node 会写入该文件。在开发者机器上,如果不存在占位符 .npmrc,npm 会忽略 NODE_AUTH_TOKEN。

本地发布(开发者终端)

签发令牌前,先检查现有认证:

npm whoami --registry https://registry.npmjs.org
echo "${NPM_TOKEN:+NPM_TOKEN is set}"
cat ~/.npmrc 2>/dev/null | grep -v authToken | head
grep -l 'NPM_TOKEN' ~/.zshrc ~/.bashrc ~/.zprofile ~/.bash_profile 2>/dev/null

接入令牌(任选一种):

# 1) CLI flag (most reliable locally; do NOT use in CI logs)
npm publish --access public --//registry.npmjs.org/:_authToken="${NPM_TOKEN}"

# 2) Temporary .npmrc (session-scoped)
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
npm publish --access public
rm .npmrc

# 3) Browser 2FA login (no token needed)
npm login && npm publish --access public

防护措施: 在本地终端中,--//registry.npmjs.org/:_authToken=TOKEN 不会带来安全风险。references/auth/granular-tokens.md 中标记为“错误”的内容仅适用于 CI 日志。

CI 发布(GitHub Actions)

纯可信发布——无需 npm 密钥:

permissions:
  contents: read
  id-token: write
steps:
  - uses: actions/setup-node@v6
    with:
      node-version: '24'
      registry-url: 'https://registry.npmjs.org'
      package-manager-cache: false
  - run: npm publish --access public

令牌认证——在发布步骤中设置 NODE_AUTH_TOKEN 环境变量,并为 setup-node 设置 registry-url:

- uses: actions/setup-node@v6
  with:
    registry-url: 'https://registry.npmjs.org'
    package-manager-cache: false
- run: npm publish --access public
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
诊断“令牌应绕过双重验证,却仍出现 EOTP”

如果具有“绕过 2FA”权限的细粒度自动化令牌仍触发 EOTP:

  1. npm 没有使用你的令牌——而是回退到了交互式会话认证。
  2. 运行 npm whoami。如果显示个人用户名,即可确认当前启用的是会话认证。
  3. 修正接入方式(本地使用 CLI 标志,CI 中使用 setup-node + NODE_AUTH_TOKEN)。不要轮换令牌。

npm whoami 无法验证可信发布。OIDC 认证仅在执行 npm publish 时生效。

版本管理模型 — 选择模型,而非工具

需求选择适用场景不适用场景阅读
每次可发布的合并都发布semantic-release单个软件包、严格遵循约定式提交、不需要人工把关Monorepo、提交信息不规范、团队希望审查 Release PRreferences/versioning/semantic-release.md
可审查的 Release PR,合并后发布release-please已有约定式提交,团队希望设置人工合并把关提交信息不可靠,或目标平台为零处理references/versioning/release-please.md
每个 PR 指定版本意图,批量发布changesetsMonorepo、没有约定式提交的单软件包项目、需要明确的版本说明仓库希望合并即发布,且不需要人工编写版本数据references/versioning/changesets.md
不常见或简单的发布手动触发 + npm version自动化的成本高于发布频率任务明确要求全面自动化对应工作流文件中的“手动触发”部分

版本管理规则:

  • Monorepo 的默认选择:changesets。仅当约定式提交已用于驱动仓库时才使用 release-please。
  • changesets 并非仅适用于 Monorepo。没有约定式提交、但希望通过人工审查 Version PR 的单软件包仓库,也是有效的使用场景。
  • 区分全新项目(“团队今后会采用约定式提交”)和现有仓库(“提交记录中已没有约定式提交”)。历史记录不一致的现有仓库应使用 changesets,而非 semantic-release。
  • 对于已有发布版本的软件包,在首次自动运行前先初始化基准状态(semantic-release 需要初始标签;release-please 需要一致的配置和清单;changesets 需要初始化配置)。

防护规则: release-please 清单中的“当前版本” = package.json 中的版本。对于全新且从未发布过的软件包,应将其设为 package.json 中的版本(通常为 1.0.0 或 0.1.0)。不要猜测为 0.0.0。

工作流模板 — 不要凭记忆手动拼装 YAML

身份验证版本管理模板
OIDCsemantic-releasereferences/workflows/oidc-workflows.md → 1. OIDC + semantic-release
OIDCchangesetsreferences/workflows/oidc-workflows.md → 2. OIDC + changesets
OIDCrelease-pleasereferences/workflows/oidc-workflows.md → 3. OIDC + release-please
OIDC手动触发references/workflows/oidc-workflows.md → 4. OIDC + 手动触发
Tokensemantic-releasereferences/workflows/token-workflows.md → 1. Token + semantic-release
Tokenchangesetsreferences/workflows/token-workflows.md → 2. Token + changesets
Tokenrelease-pleasereferences/workflows/token-workflows.md → 3. Token + release-please
Token手动触发references/workflows/token-workflows.md → 4. Token + 手动触发

Monorepo:选择工作区工作流前,先阅读 references/monorepo-publishing.md。优先选择 changesets 模板;如果已采用约定式提交,则可改用 release-please;不要默认在 Monorepo 中使用 semantic-release。

防护规则: 工作流模板是完整 GitHub Actions YAML 的唯一依据。版本管理参考文档介绍工具配置、自定义方式和特定工具的故障模式,并非独立的 YAML 来源。

实施前提

Package + repo
  • 代码已推送到 GitHub 仓库。
  • package.json.repository.url 与 GitHub 仓库 URL 完全一致,包括大小写。
  • 作用域公共包设置 publishConfig.access: "public"(或等效配置)。
  • 对于纯可信发布,不要设置 publishConfig.provenance;npm 会为符合条件的公共包自动生成 provenance。provenance 配置仅适用于令牌 + provenance 发布流程。
  • 提交锁文件;CI 使用与之匹配的确定性安装方式。
  • npm pack --dry-run 的结果符合预期 tarball 内容。如果其中包含 src/,而 main/module/types/exports 指向 dist/,请停止并先修复打包配置,再处理 CI。
  • 打包结构(files、exports、类型、双 ESM/CJS):references/package-config.md。
锁文件和包管理器检测
锁文件 / 标记安装备注
package-lock.json 或 npm-shrinkwrap.jsonnpm ci未使用其他包管理器时的默认选项
pnpm-lock.yamlpnpm install --frozen-lockfile通过 Corepack 启用 pnpm
yarn.lock + .yarnrc.yml 或 packageManager: yarn@…yarn install --immutableYarn Berry / 现代 Yarn
没有 Berry 标记的 yarn.lockyarn install --frozen-lockfileYarn Classic
bun.lockbbun install --frozen-lockfile仅当仓库已使用 Bun 时

存在多个锁文件时:先停止并协调包管理器的选择,再更改发布自动化配置。

CI
  • 使用 actions/setup-node,并设置 registry-url: https://registry.npmjs.org。
  • 构建 / 测试在发布所在的同一作业中运行(或作为其上游步骤运行)。
  • 设置 concurrency 以避免发布冲突。
  • 权限遵循最小权限原则,并明确指定。
  • 模板使用 actions/setup-node@v6、Node 24;除非仓库有意保留可读取标签的示例,否则设置 package-manager-cache: false。
  • 生产环境中:将 Actions 固定到完整 SHA,并附上标签注释——参见 references/supply-chain.md。
首次发布引导(新项目 → OIDC)

注意事项: 可信发布要求 npm 上已经存在该包。全新包必须先通过令牌身份验证完成引导,再关联可信发布。

  1. 在 npmjs.com 创建细粒度访问令牌(references/auth/granular-tokens.md)。
  2. 将其添加为 GitHub Actions 密钥中的 NPM_TOKEN。
  3. 发布一次:npm publish --access public,或使用基于令牌的工作流模板完成首次发布。
  4. 前往 https://www.npmjs.com/package/<your-package>/access → Publishing access → Add GitHub Actions,关联仓库。
  5. 移除 NPM_TOKEN,并将工作流切换为纯 OIDC。
迁移前提
  • semantic-release:获取完整 Git 历史记录(fetch-depth: 0)并设置基线标签。
  • release-please:配置和清单与当前 package.json 版本保持一致。
  • changesets:制定贡献者添加 changeset 的规则,并明确处理空 changeset。

防护措施 — 配置不完整的发布自动化比没有更糟

  • 优先使用 OIDC,而不是细粒度令牌;优先使用细粒度令牌,而不是经典自动化令牌。
  • 对于 monorepo,除非有充分的现有理由,否则优先使用 changesets,而不是 semantic-release。
  • 如果团队希望通过人工审核 Release PR,则优先使用 release-please,而不是 semantic-release。
  • 优先使用参考资料中的工作流模板,不要凭记忆编写 YAML。
  • 如果没有真正使用 conventional commits、fetch-depth: 0,以及支持所选身份验证方式的最新工具链,就不要选择 semantic-release。
  • release-please 需要采用双作业模式:一个作业创建/更新 Release PR,另一个发布作业仅在 release_created == 'true' 时运行。
  • 不要假定 OIDC 可在自托管运行器上使用。
  • 不要提交包含令牌的 .npmrc 文件。使用占位符的 .npmrc 没问题,但不能包含真实令牌。
  • 不要忘记设置作用域公共包的访问权限;作用域包出现 E403 通常意味着尚未配置 publishConfig.access: "public"。
  • 不要在纯可信发布基线中添加 --provenance。仅在令牌 + provenance 流程中使用。
  • 不要使用 pull_request_target 向不可信代码暴露发布密钥。
  • 如果仓库正处于迁移过程中,请一并完成身份验证 + 版本管理 + 工作流 + bootstrap。不要发布半成品。

验证脚本

内置辅助脚本 — 查看配套的 .md 文件了解标志;正常使用时不要加载脚本源代码。

脚本用途
scripts/check-package-json.mjs检查 package.json,检测包管理器/锁文件,标记元数据及 src/dist 不匹配;输出 JSON 和人类可读内容。
scripts/dry-run-publish.sh运行 npm pack --dry-run(并可选择运行 npm publish --dry-run),但不实际发布。
scripts/check-npm-auth.sh令牌身份验证诊断:检查令牌环境变量是否存在,并在预期使用令牌身份验证时运行 npm whoami。不会验证可信发布。

声明完成前的验证

务必运行:

  • scripts/check-package-json.mjs [package-dir](或在目标仓库中运行等效命令)
  • scripts/dry-run-publish.sh [package-dir] 或 npm pack --dry-run
  • 在执行发布的同一工作流中进行构建和测试
  • 检查所选版本管理工具是否已接入,而不只是已安装

身份验证相关:

检查项OIDC令牌
运行器GitHub 托管/受支持的云平台任意
权限contents: read、id-token: write无,除非使用令牌 + provenance
注册表setup-node → registry-url: https://registry.npmjs.org相同
密钥配置无(不使用 NODE_AUTH_TOKEN)NPM_TOKEN 密钥,发布时设置 NODE_AUTH_TOKEN 环境变量
身份验证诊断仅发布时执行;npm whoami 不能证明 OIDC 已生效scripts/check-npm-auth.sh --token 或 npm whoami
发布后npm audit signatures仅在预期使用 provenance/签名时运行 npm audit signatures

工具相关:

工具空运行关键文件关键检查
semantic-releasenpx semantic-release --dry-run.releaserc / release.config.js完整 Git 历史、基线标签、插件顺序
changesetsnpx changeset status.changeset/config.json发布/版本 PR 流程与模板一致
release-pleaserelease-please release-pr --repo-url=<owner/repo> --token=TOKEN --dry-run(可选).release-please-config.json、.release-please-manifest.json清单版本与 package.json 一致;发布受 release_created == 'true' 条件控制

**防护措施:**release-please 没有内置的等效空运行功能。请验证配置和清单文件,并确保清单与 package.json 相符。

输出约定

完成设置或诊断后,请报告:

  • 选定的身份验证路径和版本管理模型
  • 已更改的文件
  • 确切的发布工作流触发条件
  • 包名、版本、npm dist-tag
  • npm 包 URL(https://www.npmjs.com/package/<name>)
  • 若流程会创建 GitHub Release / 标签,请提供其 URL
  • 实际运行的验证命令
  • 来源证明 / 签名验证状态
  • 发布失败或错误发布时的回滚或恢复说明

恢复路径

如果任务涉及已有故障,请直接跳转到最精简的参考资料。

问题首先阅读重点
OIDC / 来源证明失败references/common-issues.md,然后阅读 references/auth/oidc-trusted-publishing.md缺少 id-token: write、缺少 contents: read、仓库 URL 错误、自托管运行器、缺少 npmjs 注册表配置
Token 身份验证失败references/common-issues.md,然后阅读 references/auth/granular-tokens.mdToken 已过期、作用域错误、密钥接线错误、轮换失误
semantic-release 失败references/common-issues.md,然后阅读 references/versioning/semantic-release.md浅克隆、缺少基准标签、提交不可发布、插件版本过旧
changesets 失败references/common-issues.md,然后阅读 references/versioning/changesets.md忘记添加 changesets、Release PR 偏离、访问权限 / 公共配置、预发布状态
release-please 失败references/common-issues.md,然后阅读 references/versioning/release-please.md清单偏离、没有可发布的提交、重复 / 卡住的 Release PR、发布门控损坏
发布了错误版本 / 包损坏references/common-issues.md若允许,在 72 小时内取消发布;否则弃用该版本并发布修复版本
Token 泄漏 / 安全事件references/supply-chain.md撤销、轮换、审计发布记录、加固工作流后再重新启用发布

按场景选择最精简的阅读集

  • 公开的单个包,全自动发布: references/auth/oidc-trusted-publishing.md + references/versioning/semantic-release.md + references/workflows/oidc-workflows.md(#1)+ references/supply-chain.md。
  • 公开的单个包,需要可审核的门控: references/auth/oidc-trusted-publishing.md + references/versioning/release-please.md 或 references/versioning/changesets.md + references/workflows/oidc-workflows.md(#3 或 #2)+ references/supply-chain.md。
  • 单体仓库 / 工作区: references/monorepo-publishing.md + references/versioning/changesets.md(默认)或 references/versioning/release-please.md + 对应的 OIDC / Token 工作流章节 + references/supply-chain.md。
  • 私有包、自托管运行器或非 GitHub CI: references/auth/granular-tokens.md + 选定的版本管理参考资料 + references/workflows/token-workflows.md 中的对应章节。
  • 现有工作流失败: references/common-issues.md + 当前模式的身份验证参考资料 + 当前工具的版本管理参考资料。

已知陷阱 — 快速参考

陷阱影响修复方法
在本地设置 NODE_AUTH_TOKEN 环境变量,但未配置 setup-node 的 .npmrcP0 — npm 会忽略令牌,转而要求交互式登录,出现 EOTP本地使用 --//registry.npmjs.org/:_authToken=TOKEN;CI 中同时使用 setup-node 和 NODE_AUTH_TOKEN
遇到 EOTP 就认定令牌类型错误P0 — 误诊EOTP 表示 npm 正在使用交互式会话身份验证,而不是你的令牌。应修复配置连接,而非更换令牌。
未检查 ~/.zshrc / ~/.bashrc 中是否已有 NPM_TOKENP1 — 重复签发令牌向用户索要新令牌前,先运行 grep NPM_TOKEN ~/.zshrc ~/.bashrc
设置了 NODE_AUTH_TOKEN / NPM_TOKEN,却称之为“OICD”P0 — 身份验证方式悄然出错OIDC = 不需要 npm 密钥。只要令牌在作用域内,使用的就是令牌身份验证。
对从未发布过的包首次发布时使用 OIDCP0 — 404先用细粒度令牌完成初始化,再在 npm 上关联仓库后切换到 OIDC
使用 semantic-release / release-please,却不采用约定式提交P0 — 发布受阻如果团队不愿采用约定式提交,请使用 changesets
认为 --//registry.npmjs.org/:_authToken=TOKEN 永远是错误做法P1 — 阻碍本地发布“错误”的说法仅适用于 CI 日志;在本地,CLI 标志是最可靠的形式
认为 changesets 仅适用于 monorepoP1 — 工具选错changesets 适用于单包仓库,且不要求采用约定式提交
混淆新项目的“将采用”和现有项目的“尚未采用”P1 — 指引错误新项目可以采用;尚未采用约定式提交的现有仓库需要使用 changesets
从版本管理参考文档复制配置,而非从工作流模板复制P1 — 配置不匹配工作流模板是基准;版本管理参考文档用于自定义
在生产环境中使用 @v4 操作标签P1 — 供应链风险固定到完整 SHA,并添加标签注释;请参阅 references/supply-chain.md
release-please 清单版本与 package.json 不一致P1 — release-please 出错清单必须与 package.json 完全一致,新项目也不例外

最后提醒

让 SKILL.md 聚焦于决策、顺序和防护措施。只阅读:

  1. 身份验证参考文档,
  2. 版本管理参考文档,
  3. 工作流模板中的确切章节,
  4. 以及仅在需要时阅读 references/common-issues.md / references/supply-chain.md。

当参考文档已有相关内容时,不要在这里扩展为完整的 YAML 或打包深度讲解。

评论

支持 Markdown