今日全栈架构审查揭示了关键 Bug 与技术债务——不是修修补补,是根源修复
2026-05-02
今天对 LessJS Framework 进行了一次端到端的全栈架构审查。结果符合预期——也超出预期。符合预期的是,写出好软件的唯一办法就是反复审查;超出预期的是,找到的不是表面 Bug,而是设计层面的系统性缺口。
SSG 生成的页面完全没有 CSS。根因:extractLitStyles() 尝试读取 Lit 3.x
中不存在的 CSSResult.strings 属性。Lit 3.x 使用 cssText 属性作为
CSSResult 的序列化接口,但代码仍然用 Lit 2.x 的 API。
修复:直接使用 cssText,删除 42
行无效代码和过时的数据结构构造逻辑。没有变通方案,没有兼容层——就是用对的 API。
api-consumer 组件永远卡在 "Contacting server..." 状态。根因:_fetchStatus() 在 connectedCallback() 中同步调用,而 LitElement 的首次
update cycle 尚未完成——reactive property 被设置但 DOM 还没渲染。
修复:将初始化逻辑推迟到 updateComplete.then(() =>
this._fetchStatus())。这是 Lit 的基本规则:connectedCallback 做
setup,updateComplete 做首次状态驱动操作。
多个包同时维护 deno.json、package.json、jsr.json
三份配置文件,5 个包的版本号互不一致。
决策:每个包统一为单 deno.json,删除 jsr.json
和不必要的 package.json。Deno 是第一运行时,不假兼容。
| Package | Lines of Code | Test Lines | Test Ratio | Status |
|---|---|---|---|---|
@lessjs/adapter-lit |
— | 0 | 0% | 最危险的缺口(两个 Bug 均出此处) |
@lessjs/rpc |
— | — | 184% | 项目最佳 |
| 全项目 | 13,000 | 5,500 | 42% | 总体良好,但分布严重不均 |
escapeHtml
实现。各自用不同编码逻辑——一个用正则、一个用 DOM API、一个手动替换。
审查产出了 10 条设计原则。以下是 6 条新增的(已有 4 条保留):
禁止在 connectedCallback 中同步设置 reactive property。必须在
updateComplete.then() 之后执行首次状态驱动操作。这条原则直接来自 Bug #2。
每个 adapter 必须有测试——这不是"nice to have",而是"上线前提"。如果 adapter-lit 有测试,CSS 注入 Bug 和 upgrade 竞态在提交前就会被测出来。
构建错误永远不能静默。SSG 页面生成失败时必须有明确的终端输出和构建退出码。用户不应该在浏览器里看到空白页面才能发现构建已经失败。
所有 Island 默认按需升级。只有标记为 eager 或在首屏的组件才在初始 Bundle
中包含。全局 island entry 对没有交互的页面来说是不可接受的。
每个组件的 CSS 只有一个来源。不可以在 UI 库和 SSG 管线中重复定义样式提取逻辑。cssText 是 Lit 的序列化接口——用它。
每个包只有一个配置文件:deno.json。不维护 package.json 或 jsr.json 的冗余副本。版本号只有一个真实来源。
基于这次审查,新的路线图被重新排序:先修可信度与安全,再谈更大的语法和生态扩展。
Lit 当前需要 58KB gzip 运行时。这个成本在首屏加载时集中出现——即使只有 1 个组件也需要整个运行时。
.less 编译器的愿景:将 .less 模板文件编译为原生 Custom
Element——无框架运行时。Lit 作为可选 fallback 保留,供需要 Lit 生态(context
protocol、decorators、ReactiveController)的用户选择。
这不是"替代 Lit"——这是让 Lit 从必选变成可选。零框架运行时始终是方向。