# v0.11.0 Release — 设计文档

> 生成：2026-07-13。触发：INFRA-F61 consumer 冒烟（MicroApps）暴露「published `0.10.1`（2026-06-15）严重落后 repo HEAD（308 commits 未发布）」+ tree-shaking 失效（不用 Chart 的 consumer 硬吃 ~1.3MB echarts）。
> 状态：**设计已 owner 认可**（含两个工程难点方案 A/B）。下一步 → writing-plans。
> 关联：[[INFRA-F61]] · [[INFRA-F65]]（echarts）· [[INFRA-F59]]（prop 改名）· [[INFRA-F55]] 支柱①（token 出口）· [[INFRA-F60]]（组合契约）

---

## 1. 背景（F61 冒烟实测证据）

隔离 fresh consumer（scratchpad，绕开 MicroApps sibling-symlink）实测：

- **published `0.10.1` = 2026-06-15 状态**：图表库仍是 chart.js/vue-chartjs（peerDependencies），exports 无 `./tokens`/`./composition`，无 i18n。消费方 `npm install` 拿到的是一个月前的包。`git log v0.10.1..HEAD` = 308 commits。
- **tree-shaking 完全失效**（实测因果对照）：consumer `import { Button }` 与 `import { Button, Pagination, Icon }` 主 chunk 几乎一样大（1,827 vs 1,843 kB）；vs 零-DS 基线 59 kB。barrel 主入口无条件把全部 ~40 组件 + Chart + echarts core 拖进主 chunk（实证 echarts 运行时符号 `coordinateSystem`×39 / `getZr`×19 在主 chunk）。
- **HEAD 比 published 更糟**：published 的 chart.js 是 peerDep（consumer 可排除）；HEAD 的 echarts 是 inline（硬进 bundle 无法排除）。gzip 后 584 kB 是真实代码，consumer re-minify 甩不掉。

capability 1「开发 npm install 即用」当前交付给消费方的是 stale 版本，且体积体验差。这直接阻塞 RC / v1.0（RC 若用 published 包 = 测一个月前死代码）。

## 2. 目标 & 范围

一次 breaking minor 版本（pre-1.0 breaking→minor convention），收口三件事：

1. **修发版鸿沟** — 把 06-15 以来未发布的工作正式发出去（正确的 changeset 覆盖）。
2. **拆 Chart 治 echarts** — Chart 移到 `./chart` 子路径 export，echarts 彻底离开主入口/主 chunk。
3. **`sideEffects` 标注** — 让主入口剩余组件对 consumer 可 tree-shake。

### 明确 out-of-scope（YAGNI）

- **preserveModules 多入口根治（tree-shaking #3）** — build 架构大改，改 dist 全部产物结构、风险高、验证面广；与发版鸿沟正交。独立排期，有真实 consumer 反馈后再评估。
- **live Figma 保真度抽查** — 另一条线（capability 2），不在本版。
- **RC / v1.0 stamp** — 本版发布后另议（owner 显式 go）。

## 3. 关键决策记录

| # | 决策 | 选择 | 理由 |
|---|---|---|---|
| D1 | Chart API 形态 | **`./chart` 子路径 export** | 最彻底（echarts 绝不进主 chunk）；0.11.0 本就 breaking，并进不增加迁移轮次 |
| D2 | 0.11.0 tree-shaking 范围 | **只 #1（Chart 拆）+ #2（sideEffects）** | #1 砍掉单一最大块 echarts；#3 是正交大改，独立排期 |
| D3 | UMD × 多入口冲突（难点 A） | **index 保持 ESM+UMD 双出；chart 作为额外 ESM-only 子入口** | Vite lib 多入口不支持 UMD；图表消费方都是现代 bundler（走 exports.import），不需要 Chart 的 UMD；index 的 `require()`(.umd.cjs) 路径不破坏 |
| D4 | Chart CSS 归属（难点 B） | **给 chart 出独立 `./chart/style.css`**（含 chart scoped 样式 + `--chart-color-*` token） | `./chart` 自包含、按需；只 import `./chart` 的 consumer 不缺 chart token |

## 4. 详细设计

### 4.1 Chart 拆分 → `./chart`

- **新建入口** `src/chart.ts`：`export { default as Chart } from './canonical/Chart.vue'`。
- **文件不移动**：`src/canonical/Chart.vue`（薄 wrapper + `data-figma-*` 溯源）→ `src/components/Chart/Chart.vue`（BaseChart，唯一 `echarts/core` tree-shaken import 处：PieChart/BarChart/LineChart + Legend/Tooltip/Grid + SVGRenderer，`echarts.use()`）路径均不动。web-components build（`vite.web-components.config.ts`）依赖 canonical/Chart.vue 路径不变 → 不受影响。
- **主入口 `src/index.ts` 删 3 处**：`import Chart`（line 23）、named export `Chart,`（line 67）、`app.component('Chart', Chart)`（line 134）。
- **全局插件（`install()`）不再注册 Chart** → `app.use(TVU)` 消费方失去全局 `<Chart>`。**breaking，changelog 明写迁移**（改为局部注册：`import { Chart } from '@ux-team/tvu-design-system/chart'`）。
- **`src/canonical/index.ts`**：`export { default as Chart } from './Chart.vue'` 保留（canonical barrel 是内部/react-pilot 用途，不是 npm 主入口；保留不影响主入口 tree-shaking）。

### 4.2 vite build（难点 A 落地）

- `build.lib.entry` 保持 `src/index.ts` 单入口出 ESM(`tvu-design-system.js`) + UMD(`.umd.cjs`)。
- 额外用 `rollupOptions.input`（或第二次 build pass）为 `src/chart.ts` 出 **ESM-only** `dist/chart.js` + `dist/chart.d.ts`。
- `external: ['vue']` 不变；echarts 仍 inline（现在只 inline 进 chart chunk，不进 index）。
- 若单次 build 两入口共享 echarts 有重复打包风险，用 `output.manualChunks` 或确保只 chart 入口引 echarts（index 已不引）。

### 4.3 Chart CSS 拆分（难点 B 落地）

- 现状：`cssCodeSplit: false` → 全部 scoped 样式 + `variables.css` 的 `--chart-color-1..10`（variables.css line 104-113）合进单一 `dist/style.css`。
- 目标：BaseChart `<style scoped>`（Chart.vue line 87-99）+ `--chart-color-*` token 拆出 → `dist/chart/style.css`；主 `dist/style.css` 保留其余（chart token 从主 style.css 移除，避免只用主库的人也带图表色，非必须但更干净——**实现时确认移除不破坏其它组件对 chart token 的引用**，若有共享则保留在主 style.css）。
- `package.json` 新增 `exports["./chart/style.css"]`。

### 4.4 package.json exports 变更

```
新增：
  "./chart":        { "import": "./dist/chart.js", "types": "./dist/chart.d.ts" }
  "./chart/style.css": "./dist/chart/style.css"
新增：
  "sideEffects": ["**/*.css", "./dist/style.css"]
```
（`./`、`./style.css`、`./tokens`、`./composition`、`./icons/*`、`./eslint-plugin` 不变。）

### 4.5 发版 changeset（现有 4 个欠缺，新增 4 个）

`.changeset/` 现有：`infra-f59-*`(minor)、`pagination-selectbox-radio-host-fix`(patch)、`tooltip-keyboard-a11y`(patch)、`topbar-right-content-anchor`(patch)。**新增**：

- `echarts-migration.md`（**minor**）：chart.js/vue-chartjs peerDep 移除（peerDeps 仅剩 vue）+ 图表引擎换 echarts + **Chart 移到 `./chart` 子路径、全局插件不再注册 Chart**。
- `token-exports.md`（**minor**）：`./tokens`(DTCG JSON) + `./tokens/js`(resolved TS) 出口。
- `composition-exports.md`（**minor**）：`./composition`(+`/js`) 组合契约出口。
- `i18n-locale.md`（**minor**）：`provideTvuLocale`/`useLocale`/`defaultLocale`/`TVU_LOCALE_KEY` + type `TvuLocale`（非破坏默认英文）。
- （可选 patch）font-family pin 修复 + CE/dual-framework 渲染修复 —— 按是否属 npm 包表面判定后决定是否列。

### 4.6 迁移文档（Breaking 汇总）

`MIGRATION_TO_V1.md` / `CHANGELOG` 增 0.11.0 段：

1. **Chart import 路径变** + chart.js/vue-chartjs peerDep 移除（不再需要安装图表 peer 库）。
2. **F59 prop 改名（无 runtime 兜底，旧名走 fallthrough attrs 静默失效）** 对照表：
   - Button `style`→`fill`（React 侧 `variant`→`fill`）
   - Badge `tag`→`fill`
   - Tab/TabList/TabItem `type`→`fill`；`property2`→`color`；TabItem `property1`→`state`
   - Steps/StepItem `stepStyle`→`type`；**StepItem 删 `style`**
   - InputNumber `property1`→`type`
   - （枚举值 / Figma 属性名不变；prop-aliases.json 记录的是 Figma↔code 命名映射，非旧-code-名 runtime 兜底）

## 5. 需同步更新的文件面

`docs/API_STABILITY.md`(line 22 Chart 稳定 API 表 → 标注 `./chart` import 路径)、docs 站 ChartPage.vue/navigation.ts（跟随新入口）、`MIGRATION_TO_V1.md`。**顺手修**：`scripts/generate-render-verification-manifest.mjs`(line 504-519) Chart 条目的 stale "Chart.js/canvas" 注释（实为 echarts SVG）。

现有 gate 均按组件名/demo 文件路径断言（`audit-figma-library-vs-canonical` KNOWN set / `audit-demo-framework-parity` 硬编码 demo 路径 / manifest 按 codeComponent 名），**纯拆 export 路径不撞 gate**（已实证无 bundle-content/bundle-size gate）。

## 6. 验证策略

- **既有链**：`pnpm build`（vue-tsc + vite build ×2 入口 + token/composition/icon 生成）+ prepublishOnly 全套 audit + 515 vitest。
- **tree-shaking 回归断言（新增，核心 DoD）**：复跑 F61 隔离 consumer 冒烟——
  - `import { Button }`：主 chunk **不含 echarts 符号**（grep `coordinateSystem`/`getZr` = 0），gzip 预期 < 150 KB（vs 现 584 KB）。
  - `import { Chart } from '.../chart'` + `import '.../chart/style.css'`：Chart 渲染正常、echarts 在 chart chunk。
- **consumer 冒烟复跑**：`npm pack` HEAD → 装隔离 consumer → build，验证全部 exports（`. / style.css / chart / chart/style.css / tokens / tokens/js / composition / composition/js / icons/* / eslint-plugin`）可解析。

## 7. 风险 & 回滚

| 风险 | 缓解 |
|---|---|
| 多入口 build 把 echarts 重复打进 index + chart | build 后 grep 确认 index chunk 无 echarts 符号（回归断言已覆盖）|
| chart CSS 拆分漏 token → chart 掉色 | consumer 冒烟渲染 Chart 验证；chart token 若被非-chart 组件共享则保留主 style.css |
| UMD 消费方用 Chart | 现无已知 UMD-Chart 消费方；UMD(index) 本就不该含重依赖；changelog 注明 Chart 仅 ESM 子路径 |
| changeset 遗漏未发布大项 → changelog 缺项 | 本设计 §4.5 已盘点 4 大遗漏；发版前对 `git log v0.10.1..HEAD` 复核 |
| 回滚 | 纯增量 + 删 3 行；Chart 拆分若出问题可临时把 Chart 重新加回主入口 barrel（放弃 tree-shaking 收益但不破坏发布）|

## 8. 开放问题

无（两个工程难点 A/B 已 owner 认可 → D3/D4）。
