0006: Version Strategy
v0.7–0.11 progressive stabilization → v1.0 API stability promise → v1.x incremental → v2.0 only if needed.
Adopted
Source: docs/decisions/0006
<h1>ADR 0006: 版本号策略 — 从 0.6 到 2.0 的递进路线</h1>
<h2>Status</h2>
<p><strong>ADOPTED</strong> — v0.6.2 架构决策,替代旧 roadmap 中的 v0.7~v0.10 线性递增方案。</p>
<h2>Context</h2>
<p>LessJS 当前的 roadmap 采用 0.7 → 0.8 → 0.9 → 0.10 的线性递增。这个方案有几个问题:</p>
<ol><li><strong>SemVer 语义不精确</strong>:0.7(Island Manifest)到 0.8(Fullstack)是架构能力的质变,不是量变。Patch 级别的递增不能传达这种差异。</li><li><strong>1.0 的门槛模糊</strong>:什么时候可以打 1.0?是 P2 审计修复完成后?还是 Compiler 完成后?没有明确的判定标准。</li><li><strong>Compiler 和 Fullstack 的归属不清</strong>:这两个能力会改变"LessJS 是什么"的定义。如果放在 1.0 之后,就是 Breaking Change 需要升 2.0;如果放在 1.0 之前,它们还是 0.x 的正常演化。</li><li><strong>审计发现尚未纳入</strong>:2026-05-07 四维审计的 P0/P1/P2 修复任务没有对应的版本号。</li></ol>
<h2>Decision</h2>
<p>采用<strong>三段式版本路线</strong>,以"能力域"划分 MAJOR/MINOR,而非线性递增:</p>
<h3>版本总览</h3>
<pre><code>v0.7.0 ← P0 稳定基线(审计修复)
v0.8.0 ← P1 功能完善 + Island Manifest
v0.9.0 ← Serverless Fullstack
v0.10.0 ← SSG + ISR + PWA
v0.11.0 ← P2 基础设施 + .less Compiler Alpha
v1.0.0 ← API 稳定承诺
v1.x ← 增量演进(不破坏公共 API)
v2.0.0 ← Compiler 成为默认(如需 Breaking Change)</code></pre>
<h3>判定 1.0.0 的标准</h3>
<p>1.0.0 不是一个"完成了所有功能"的版本号,而是一个<strong>公共 API 稳定承诺</strong>的信号。以下条件全部满足时,可以打 1.0.0:</p>
<table><thead><tr><th>#</th><th>条件</th><th>理由</th></tr></thead><tbody><tr><td>1</td><td>核心模块测试覆盖率 ≥ 80%</td><td>覆盖率是 API 稳定的前提——没有测试的 API 无法保证行为不变</td></tr><tr><td>2</td><td>CI 全链路门禁就位(test + typecheck + lint + coverage gate)</td><td>自动化防止退化</td></tr><tr><td>3</td><td>runtime-shim 由 AST 生成,不再手工维护</td><td>最大技术债消除,SSR 输出一致性可验证</td></tr><tr><td>4</td><td>公共 API 列表明确文档化(exports、config options、CLI flags)</td><td>用户知道哪些是承诺的,哪些是内部的</td></tr><tr><td>5</td><td>至少 3 个真实项目 dogfooding(含 docs 站)</td><td>实际使用验证</td></tr><tr><td>6</td><td>无 P0/P1 级已知 Bug</td><td>质量基线</td></tr></tbody></table>
<p><strong>1.0.0 不要求</strong>:Compiler 生产可用、ISR 生产可用、Fullstack 示例丰富。这些是 1.x 的增量工作。</p>
<h3>各版本详细规划</h3>
<h4>v0.7.0 — 稳定基线(P0 审计修复)</h4>
<p><strong>定位</strong>:消除不可信行为,建立工程纪律。</p>
<table><thead><tr><th>任务</th><th>优先级</th><th>说明</th></tr></thead><tbody><tr><td>render-dsd.ts 单元测试</td><td>P0</td><td>770 行核心渲染器零覆盖</td></tr><tr><td>island.ts 单元测试</td><td>P0</td><td>321 行 Island 系统零覆盖</td></tr><tr><td>runtime-shim 一致性测试 + 修复</td><td>P0</td><td>serializeAttributes 缺失 escapeAttrValue</td></tr><tr><td>headExtras/headFragments XSS 修复</td><td>P0</td><td>重命名 + 运行时警告</td></tr><tr><td>消除静默 catch → console.warn</td><td>P0</td><td>8+ 处错误吞没</td></tr><tr><td>CI 补全</td><td>P0</td><td>adapter-lit/docs 测试任务、发布门禁</td></tr><tr><td>pre-commit hooks</td><td>P0</td><td>格式化/lint/类型检查守卫</td></tr></tbody></table>
<p><strong>为什么是 0.7.0 而不是 0.6.3</strong>:XSS 修复和 catch 行为变更属于破坏性变更(部分用户可能依赖当前的静默行为)。SemVer 0.x 的 MINOR 升级允许破坏性变更,正好对应。</p>
<h4>v0.8.0 — 功能完善 + Island Manifest</h4>
<p><strong>定位</strong>:补全测试覆盖 + Island 系统演进。</p>
<table><thead><tr><th>任务</th><th>优先级</th><th>说明</th></tr></thead><tbody><tr><td>signals 测试套件</td><td>P1</td><td>749 行零覆盖</td></tr><tr><td>dsd-hydration.ts 单元测试</td><td>P1</td><td>Mixin 核心逻辑验证</td></tr><tr><td>Signal 原生切换</td><td>P1</td><td>npm 依赖 + globalThis.Signal 条件回退</td></tr><tr><td>render-dsd.ts 拆分为 4 模块</td><td>P1</td><td>可维护性</td></tr><tr><td>UI 组件统一到 DsdLitElement</td><td>P1</td><td>3 个组件未使用 Mixin</td></tr><tr><td>insertAfterHead 去重</td><td>P1</td><td>ui → core</td></tr><tr><td>包版本统一</td><td>P1</td><td>6 包版本不一致</td></tr><tr><td>定位重写(避免"全栈"过度承诺)</td><td>P1</td><td>诚实营销</td></tr><tr><td>Interactive Playground</td><td>P1</td><td>StackBlitz 一键体验</td></tr><tr><td>Playwright E2E 测试</td><td>P1</td><td>浏览器级集成测试</td></tr><tr><td>Island Upgrade Manifest</td><td>Roadmap</td><td>页面级 island 清单替代全局入口</td></tr><tr><td>Speculative Loading 可观测</td><td>Roadmap</td><td>eager/visible/idle 策略浏览器测试</td></tr></tbody></table>
<p><strong>合并旧 roadmap 的 v0.7 内容</strong>:Island Manifest 和 Speculative Loading 与 P1 测试/组件统一工作属于同一能力域,合并到 0.8.0 合理。</p>
<h4>v0.9.0 — Serverless Fullstack</h4>
<p><strong>定位</strong>:从"内容站框架"扩展到"轻量全栈框架"。</p>
<table><thead><tr><th>能力</th><th>说明</th></tr></thead><tbody><tr><td>FormData actions</td><td>表单提交 → 服务端 action</td></tr><tr><td>Typed RPC</td><td>端到端类型安全</td></tr><tr><td>env/secrets</td><td>环境变量安全注入</td></tr><tr><td>Deployment adapters</td><td>Deno Deploy / CF Workers / Vercel Edge</td></tr><tr><td>官方示例</td><td>内容驱动全栈应用</td></tr></tbody></table>
<p><strong>与旧 roadmap 对齐</strong>:这基本上是旧 v0.8 的内容,版本号不变。</p>
<h4>v0.10.0 — SSG + ISR + PWA</h4>
<p><strong>定位</strong>:构建能力成熟——增量构建、缓存策略、离线支持。</p>
<table><thead><tr><th>能力</th><th>说明</th></tr></thead><tbody><tr><td>路由级 revalidation</td><td>按需重新生成静态页面</td></tr><tr><td>Cache lock</td><td>并发构建时的缓存锁</td></tr><tr><td>Stale fallback</td><td>新内容构建中返回旧内容</td></tr><tr><td>Service Worker 策略</td><td>NetworkFirst/CacheFirst 可配置</td></tr><tr><td>CDN recipes</td><td>Cloudflare/Netlify 缓存配置模板</td></tr></tbody></table>
<p><strong>与旧 roadmap 对齐</strong>:这是旧 v0.9 的内容,版本号不变。</p>
<h4>v0.11.0 — 基础设施成熟 + Compiler Alpha</h4>
<p><strong>定位</strong>:消除最大技术债 + 引入 Compiler 实验性能力。</p>
<table><thead><tr><th>任务</th><th>来源</th><th>说明</th></tr></thead><tbody><tr><td>AST 代码生成替代手工 runtime-shim</td><td>P2 #19</td><td>根治 SSR 输出一致性</td></tr><tr><td>增量 SSG 构建</td><td>P2 #20</td><td>文件哈希缓存</td></tr><tr><td>性能基准</td><td>P2 #24</td><td>构建时间/产物体积/Lighthouse/竞品对比</td></tr><tr><td>覆盖率收集 + 门禁</td><td>P2 #25</td><td>CI 覆盖率强制</td></tr><tr><td>视觉回归测试</td><td>P2 #26</td><td>组件截图对比</td></tr><tr><td>依赖安全审计自动化</td><td>P2 #27</td><td>CI 集成 npm audit / Snyk</td></tr><tr><td>.less Compiler Alpha</td><td>ADR 0002</td><td>可选零框架组件编译</td></tr></tbody></table>
<p><strong>为什么 Compiler 在 P2 之后</strong>:Compiler 需要稳定的 DSD renderer 作为编译目标。如果 renderer 还在手工同步(runtime-shim 问题),Compiler 的输出也无法保证正确。P2 的 AST 替换解决了这个问题。</p>
<h4>v1.0.0 — API 稳定承诺</h4>
<p><strong>判定标准</strong>:见上文 6 条标准。</p>
<p><strong>1.0.0 的含义</strong>:</p>
<ul><li>公共 API(<code>less()</code> 配置、CLI 命令、<code>@lessjs/core</code> 导出、<code>@lessjs/rpc</code> 导出)视为稳定</li><li>Breaking Change 必须升 MAJOR</li><li>Lit adapter 继续作为一等公民支持</li><li>Compiler 仍为 opt-in,不是默认</li></ul>
<h4>v1.x — 增量演进</h4>
<table><thead><tr><th>版本</th><th>方向</th><th>说明</th></tr></thead><tbody><tr><td>v1.1</td><td>Compiler Beta → Stable</td><td><code>.less</code> 文件成为推荐组件编写方式</td></tr><tr><td>v1.2</td><td>Fullstack 示例丰富</td><td>CRM/admin 级 demo</td></tr><tr><td>v1.x</td><td>更多 adapter</td><td>Vue adapter、React island bridge 等</td></tr></tbody></table>
<blockquote><p><strong>注</strong>:<code>@lessjs/blog</code> 开发提前到 v0.8.0 后启动(SSG 插件形态,不依赖 Fullstack),在 v0.9 期间 dogfooding。v1.0 时 blog 包随主框架一起稳定。</p></blockquote>
<h4>v2.0.0 — Compiler 成为默认(如果需要)</h4>
<p>只有当以下条件同时满足时才考虑 2.0:</p>
<ol><li><code>.less</code> Compiler 生产可用且经过大量项目验证</li><li>社区已自然迁移到 <code>.less</code> 组件</li><li>将 Compiler 设为默认会破坏现有 Lit 用户的工作流</li></ol>
<p><strong>如果 Lit 兼容模式可以无缝共存,则不需要 2.0。</strong></p>
<h3>版本号语义总结</h3>
<table><thead><tr><th>版本段</th><th>含义</th><th>Breaking Change 规则</th></tr></thead><tbody><tr><td>0.7–0.10</td><td>框架在定义自己</td><td>MINOR 升级允许破坏性变更</td></tr><tr><td>0.11</td><td>过渡版本:基础设施成熟 + 新能力引入</td><td>仍允许,但应尽量减少</td></tr><tr><td>1.0</td><td>公共 API 冻结</td><td>绝不允许(必须升 MAJOR)</td></tr><tr><td>1.x</td><td>增量扩展</td><td>公共 API 不破坏</td></tr><tr><td>2.0</td><td>范式转换(如果需要)</td><td>允许,但需迁移指南</td></tr></tbody></table>
<h2>Consequences</h2>
<p><strong>正面:</strong></p>
<ul><li>每个版本号有清晰的语义——用户看到版本号就能判断升级风险</li><li>1.0.0 有明确的判定标准,不再是"感觉差不多了"的主观判断</li><li>Compiler 和 Fullstack 在 0.x 阶段完成,不用担心 1.0 后的 Breaking Change</li><li>审计发现有了正式的版本归属</li></ul>
<p><strong>负面:</strong></p>
<ul><li>0.x 阶段拉长(0.7 → 0.11 共 5 个 MINOR 版本),可能给人"不够稳定"的印象</li><li>需要在 1.0 前维护公共 API 列表,增加了文档工作量</li><li>如果 0.11 的 Compiler Alpha 发现需要调整 DSD renderer 输出格式,可能影响 1.0 的时间线</li></ul>
<p><strong>缓解:</strong></p>
<ul><li>每个 0.x 版本都应该有明确的里程碑文档,传递"渐进成熟"而非"还不稳定"的信号</li><li>公共 API 列表在 v0.8 就开始文档化(标记为 "Stable API Candidate"),让 1.0 的门槛更具体</li><li>如果 0.11 Compiler Alpha 进展顺利,可以合并到 1.0 直接发布</li></ul>
<h2>参考</h2>
<ul><li><a href="./0002-less-compiler-eliminate-lit.md">ADR 0002: .less Compiler</a></li><li><a href="./0005-with-dsd-hydration-mixin.md">ADR 0005: WithDsdHydration Mixin</a></li><li><a href="https://semver.org/">SemVer 2.0.0</a></li><li>LessJS 四维审计报告 (2026-05-07)</li></ul>
<hr>
<p>_决策日期: 2026-05-07 | 版本: v0.6.2_</p>