ha-sankey-chart 是如何构建的Lit TypeScript Web 组件架构完全指南【免费下载链接】ha-sankey-chartA Home Assistant lovelace card to display a sankey chart. For example for power consumption项目地址: https://gitcode.com/gh_mirrors/ha/ha-sankey-chartha-sankey-chart 是一款为 Home Assistant 打造的爱乐色Lovelace桑基图卡片用直观的流向图展示家庭电力、水等能耗数据。本文将带你拆解它的完整构建方案从 Lit 2.8 Web 组件框架、TypeScript 严格模式到 Rollup 打包与 Jest 测试体系带你完整理解一个生产级 HA 自定义卡片 Web 组件架构的搭建方法。技术栈总览一张表看懂架构选型项目只有 3 个运行时依赖其余全是开发工具链——这是轻依赖的典型做法角色技术版本用途UI 框架Lit2.8Web Components、响应式属性、模板渲染类型系统TypeScript4.4strict: true严格模式开发HA 集成custom-card-helpers1.9卡片接口约定setConfig、编辑器时间计算date-fns2.29time_period_from时间区间解析打包Rollup 7 个插件2.58TypeScript 编译、压缩、开发服务测试Jest ts-jest jsdom299 个测试文件 快照测试版本信息统一由 package.json 管理入口文件甚至直接import { version } from ../package.json加载时在浏览器控制台打印带样式的版本横幅方便用户排查版本问题。项目目录结构每个文件一个职责src/ ├── ha-sankey-chart.ts # 卡片入口数据获取 自动配置748 行 ├── chart.ts # 图表渲染组件 sankey-chart-base829 行 ├── section.ts / label.ts # 单列渲染与标签计算 ├── layout.ts # 横/竖向布局自动切换仅 13 行 ├── energy.ts # Home Assistant 能源数据聚合逻辑 ├── reconcile.ts # 父子数值不一致时的对齐策略 ├── migrate.ts # 旧版 v3 配置自动迁移 ├── subscribe-mixin.ts # 复刻官方 HassSubscribe 数据订阅机制 ├── types.ts # 全局配置与节点类型定义单一事实来源 ├── utils.ts # 配置规范化、状态格式化等纯函数 ├── editor/ # 可视化配置编辑器独立组件 └── localize/ # 5 种语言的多语言文案 JSON组件分层架构外层管数据内层管渲染这是整个架构最值得学习的设计——一张卡片被拆成两层 Web 组件数据层sankey-chart入口 ha-sankey-chart.ts 用装饰器注册自定义元素并继承SubscribeMixin(LitElement)customElement(sankey-chart) class SankeyChart extends SubscribeMixin(LitElement) { property({ attribute: false }) public hass!: HomeAssistantReal; state() private config!: Config; state() private states: HassEntities {};property接收 HA 注入的hass对象state的变化自动触发重新渲染——Lit 的响应式循环替代了所有手动 DOM 操作模块顶层还会把卡片注册进window.customCards让它直接出现在 HA 的卡片选择器里数据流从 YAML 到屏幕的三步走第 1 步配置校验。HA 调用setConfig()时先做类型检查再经normalizeConfig()迁移、归一化见 utils.ts配置最终只有一种内存形态。第 2 步按需拉数据。hassSubscribe()按三种模式分发energy_date_selection轮询等待同屏的 energy-date-selection 卡片就绪然后订阅 Energy Dashboard 数据流time_period_from用setInterval按throttle间隔轮询统计数据rate 模式power / water_flow读取能源偏好一次性生成图结构之后由hass.states实时驱动。第 3 步状态驱动渲染。统计结果写入state() states子组件自动更新。渲染层sankey-chart-basechart.ts 是纯渲染组件亮点在shouldUpdate里实现了 throttle 节流——高频状态变化下自动丢弃中间帧保证仪表盘不掉帧。布局决策被抽成一个 13 行的纯函数layout.ts 中的shouldBeVertical()当可用宽度小于各 section 最小宽度之和时layout: auto自动从横向翻转为纵向手机和桌面都能自适应。父子数据对不齐比如总耗电 ≠ 各房间之和由 reconcile.ts 按should_be/reconcile_to配置做数值对齐避免出现负流量。可视化编辑器sankey-chart-editor编辑器是第三个独立元素editor/index.ts实现custom-card-helpers的LovelaceCardEditor接口由卡片的静态方法getConfigElement()动态创建。关键在于编辑器与图表共用 types.ts 中的SankeyChartConfig接口YAML 里能写的选项在 UI 里都能点出来且编辑器打开时自动把旧版 v3 配置迁移成 v4 结构老用户无感升级。国际化五语言包 英文兜底src/localize/localize.ts 打包了 en、cz、sk、nl、pt-BR 五套 JSON 文案读取localStorage中的selectedLanguage决定语言任何缺失键自动回退到英文——多语言支持几乎没有增加运行时复杂度。构建工具链Rollup 打出单文件产物rollup.config.js 的插件链是标准 HA 卡片配方nodeResolve → commonjs → typescript → json → babel → (prod) minifyHTML terserexport default [{ input: src/ha-sankey-chart.ts, output: { dir: dist, format: es }, plugins: [...plugins], }];生产构建npm run build先 ESLint 再打包额外压缩模板字面量并用 terser 混淆产出单文件dist/ha-sankey-chart.js开发模式npm startrollup -w监听 本地 3000 端口静态服务配合 rollup.config.dev.js 在真实 HA 环境里热调试hacs.json 只需声明filename: ha-sankey-chart.jsHACS 用户一条命令装好这个 bundle。单 bundle 发布不是偶然HA 前端加载自定义卡片只信任一个脚本地址把 Lit、语言包、类型全部打进一个文件用户零配置。测试体系Jest jsdom 快照jest.config.js 选用ts-jest预设 jsdom 环境模拟浏览器 DOMtests/setupTests.ts 统一 mockcustom-card-helpers。9 个测试文件分工明确autoconfig.test.ts996 行覆盖楼层/区域分组、碳强度拆分等自动配置全场景basic.test.ts snapshotsDOM 快照测试防止渲染结构被无意改动migrate.test.tsv3 → v4 配置迁移的兼容性回归。值得注意的一个细节Lit 的 CSS 模板字面量在 Jest 里会干扰 babel 转译配置里用transformIgnorePatterns和moduleNameMapper精确放行lit/系列包——这是 Lit 项目写测试的常见坑。架构设计要点总结双层元素拆分sankey-chart负责数据与配置sankey-chart-base只管画——数据层坏了不用动渲染层反之亦然单一事实来源types.ts 的配置接口同时服务卡片、编辑器、测试三处杜绝结构漂移纯函数下沉布局判断、配置迁移、状态格式化全是无副作用函数如 utils.ts 的formatState单元测试成本极低数据层复刻官方模式subscribe-mixin.ts 移植自 HA 前端源码订阅/取消订阅生命周期与官方卡片完全一致不泄漏连接单文件 ES Module 产物匹配 HA 的卡片加载模型HACS 一键安装用户体验最简。这套Lit TS 严格模式 Rollup 单 bundle Jest 快照的架构是开发任何 HA 自定义卡片都可直接套用的完整参考模板。【免费下载链接】ha-sankey-chartA Home Assistant lovelace card to display a sankey chart. For example for power consumption项目地址: https://gitcode.com/gh_mirrors/ha/ha-sankey-chart创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考