怎样搭建和发布一个公司内部组件库?

先理解原理和示例,再练习完整口述与追问。

用 Vite 库模式或 Rollup 构建 ESM 与类型声明,组件按目录组织、支持按需引入;package.json 配置 exports、types、sideEffects 标记样式文件,把 Vue、React 放在 peerDependencies;样式基于 CSS 变量做主题;文档与示例用 Storybook 或 VitePress;用 changesets 管理版本与变更日志,发布到私有 npm 仓库。

框架放 peerDependencies 是为了让使用方只安装一份框架,否则会出现两个 Vue 实例导致响应式失效或 React Hook 报错。sideEffects: ["**/*.css"] 告诉打包工具除样式外的模块都可以 Tree Shaking。exports 精确声明可导入的路径(.、./button、./style.css),配合 types 条件提供 TypeScript 类型。

语义化版本:破坏性变更升主版本,新功能升次版本,修复升修订号。changesets 让每个 PR 附带变更说明,合并后自动汇总版本和 CHANGELOG。第三方依赖有 bug 而上游未修复时,可用 patch-package 生成补丁并在 postinstall 中应用,同时向上游提交修复。

json
{
  "name": "@acme/ui",
  "type": "module",
  "exports": {
    ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
    "./button": { "types": "./dist/button/index.d.ts", "import": "./dist/button/index.js" },
    "./style.css": "./dist/style.css"
  },
  "sideEffects": ["**/*.css"],
  "peerDependencies": { "vue": "^3.4.0" },
  "files": ["dist"],
  "publishConfig": { "registry": "https://npm.acme.internal/" }
}

把框架打进产物会造成重复实例;files 漏写会把源码和测试一起发布。组件的可访问性(键盘操作、ARIA、焦点管理)和视觉回归测试常被忽略。

我会用 Vite 库模式或 Rollup 输出 ESM 和类型声明,每个组件独立目录,支持按需引入;package.json 写好 exports、types、sideEffects,Vue 或 React 放 peerDependencies 避免重复实例;主题用 CSS 变量;文档用 Storybook 或 VitePress;版本用 changesets 管理语义化版本和变更日志,CI 中跑测试后发布到私有仓库。依赖有 bug 时可以先用 patch-package 打补丁。