专栏:HarmonyOS 三方库适配实战(6/30)
阶段目标:选出一个适合第一次 TypeScript → ArkTS 适配的小型候选,并把版本、许可证、测试和停止条件锁定。
摘要
新人第一次做三方库适配,最容易犯的错误不是代码写错,而是一开始就选了 UI 框架、数据库或网络 SDK:源码多、平台依赖深、异步与生命周期交织,任何一个错误都可能来自几十个位置。本文给出七道筛选门,把候选范围缩到纯算法、文本或数据转换工具,并用本地教学夹具演示如何保存候选卡、运行时耦合扫描和最小行为基线。筛选通过只代表“值得进入适配”,不代表库已经兼容 HarmonyOS。
适用范围与本篇产出
本文面向能阅读 TypeScript、但还没有独立移植经验的 HarmonyOS 开发者。你需要一个可访问的上游仓库或源码包,以及一个能够保存实验记录的目录。
完成后应得到三项产物:
- 一张带准确版本或提交号的候选卡;
- 一份运行时耦合与依赖风险扫描结果;
- 一组适配前行为基线,以及明确的继续/停止决定。
本文不判断任何未实际审计的公开库,也不把“纯 TypeScript”直接等同于“可在 ArkTS 编译”。华为官方的从 TypeScript 到 ArkTS 的适配规则列出了静态类型、对象布局、结构类型和模块语法等差异,候选仍要进入后续编译验证。
为什么第一只练手库要刻意选小
第一次适配的学习目标是走通“锁定上游—侦察—改造—构建—消费”的闭环,而不是证明自己能一次解决所有平台问题。合适的候选通常具有这些特征:
| 维度 | 推荐范围 | 危险信号 |
|---|---|---|
| 源码规模 | 核心代码几十到几百行 | 多包仓库、代码生成、大量插件 |
| API 形态 | 少量纯函数或简单类 | UI 组件、数据库连接、长生命周期对象 |
| 执行模型 | 同步逻辑为主 | Worker、复杂 Promise 链、事件循环假设 |
| 平台依赖 | 无 DOM、无 Node.js 内置模块 | fs、process、Buffer、window、document |
| 输入输出 | 字符串、数值、普通数组 | 文件句柄、Socket、原生指针 |
| 测试 | 输入与期望值清楚 | 只有截图或人工观察 |
| 许可证 | 仓库内有明确许可证文件 | 无许可证、来源不明、仅有二进制 |
“小”不是永久架构选择,而是控制第一次实验的变量数量。等第 12 篇能够稳定处理类型、平台能力和错误模型后,再扩大候选复杂度。
图 1:候选库筛选漏斗(示意图)。筛选只决定是否进入源码侦察,不代表已经兼容 HarmonyOS。
七道筛选门
第 1 道:身份能不能锁定
至少记录仓库地址、release/tag 或 commit、包坐标和获取时间。只写“最新版”无法复现。
candidate:name:"<package-name>"upstream:"<official-repository-url>"revision:"<exact-tag-or-commit>"package_coordinate:"<registry-coordinate-or-none>"captured_at:"2026-10-18T21:10:00+08:00"第 2 道:许可证能不能说明来源
检查仓库根目录的LICENSE/COPYING、包清单中的许可证字段和发布页是否一致。许可证存在不等于业务场景一定合规;如果许可证缺失、文件与声明冲突,先暂停并交由项目负责人或法务确认,不要边移植边猜。
第 3 道:核心逻辑是不是平台无关
优先选择文本规范化、编码转换、校验、排序、解析等纯计算逻辑。依赖 DOM、Node.js 内置模块或系统服务的库,会把“语言迁移”和“平台能力替换”两个问题叠在一起。
第 4 道:公开 API 能不能在一张纸上写完
第一次练手建议只保留 2~5 个公开符号。API 越窄,适配前后越容易做逐项对照,也越容易避免把内部实现误导出。
第 5 道:行为能不能自动断言
为每个核心函数准备正常值、边界值和错误值。若只能用肉眼看 UI,第一次适配会很难区分算法问题与界面问题。
第 6 道:依赖树是否足够浅
直接依赖少不代表传递依赖少。先读取锁文件和当前包管理器的依赖树;如果候选又引入解析器、网络层和原生二进制,换一个更小的练手对象。
第 7 道:失败时能不能退出
预先写停止条件,例如:发现不可替代的 Node.js 核心模块、只有其他平台闭源二进制、许可证不明、上游测试无法获得。停止条件能防止沉没成本把教学任务变成长期维护项目。
一份可以直接复用的候选评分卡
| 检查项 | 证据 | 结果 | 下一步 | | --- | --- | --- | --- | | 上游身份 | tag/commit + 获取时间 | pass/fail | 锁定快照 | | 许可证 | LICENSE 路径与声明 | pass/fail | 复核义务 | | 核心源码 | 文件数、行数、入口 | low/medium/high | 画依赖图 | | 平台耦合 | DOM/Node/动态加载扫描 | none/found | 删除/抽象/替换 | | 依赖树 | 直接与间接依赖 | shallow/deep | 锁版本 | | 测试基线 | 正常/边界/错误向量 | ready/missing | 补向量 | | 维护状态 | 最近 release/提交/issue | active/unknown | 记录风险 |用搜索先做一次低成本排雷
下面命令从源码根目录运行。rg是文本侦察工具,结果只能作为线索;注释、测试夹具和字符串字面量可能产生误报。
rg-n--glob'*.ts'--glob'*.js'`-e'eval\s*\(|new\s+Function|\brequire\s*\('`-e'\bprocess\b|\bBuffer\b|\bglobalThis\b'`-e'\bwindow\b|\bdocument\b|\blocalStorage\b'`-e'from\s+["''](?:fs|path|http|https|crypto)["'']'.有命中时不要立即判死刑。记录文件、符号、是否位于核心路径、是否能够通过注入或适配器隔离。第 7 篇会把这些命中整理成可复核的问题清单。
本专栏的教学候选怎么选
第 6~10 篇继续使用本地教学夹具@demo/text-tool@1.0.0。它只有文本规范化与非空校验两个基础 API,无子依赖、无 Native ABI,许可证字段为 Apache-2.0;本轮扫描未发现 DOM、Node.js 内置模块、动态代码执行或计时器耦合。
这里必须强调:它是为了让读者在相同工程中复现方法而制作的教学替身,不是一个外部开源库,也不能证明某个同名库可用。面对真实候选时,必须把上面的upstream、revision、许可证文件和上游测试换成真实证据。
图 2:本地教学夹具评分卡(本地复现实验记录)。许可证和真实上游身份仍需在实际候选中重新核对。
适配前行为基线可以先写成表:
| 用例 | 输入 | 期望 |
|---|---|---|
| normal-01 | " HarmonyOS library " | "HarmonyOS library" |
| boundary-01 | "HarmonyOS" | 值不变 |
| error-01 | 仅空白字符 | 抛出可识别错误 |
如果真实候选无法给出这类确定结果,就暂时不适合作为第一只练手库。
一小时试跑:把“感觉适合”变成可回放证据
第一次筛选不应停在评分表。给候选一个 60 分钟的时间盒,并要求每一步都留下可读回的产物:
| 时间盒 | 动作 | 必须保存的证据 | 立即停止条件 |
|---|---|---|---|
| 0~10 分钟 | 锁定 tag/commit、入口和许可证 | 候选卡、许可证路径 | 身份或授权无法说明 |
| 10~25 分钟 | 读取入口、依赖树并运行耦合扫描 | 命中清单、直接/间接依赖数 | 依赖闭源二进制或不可替代平台能力 |
| 25~45 分钟 | 提取 3~5 个行为向量 | 输入、预期、错误类型 | 结果依赖 UI 或外部服务且无法隔离 |
| 45~60 分钟 | 写出适配路线和最小改动面 | direct/arkts/adapter/native/stop决策 | 无法在一句话内说明下一步验证 |
决策记录不要只写“通过”。下面的格式能让下一位维护者知道结论是怎样得出的:
decision:arkts-adaptationreason:"核心为同步纯函数;命中 2 处动态对象写入,无平台 API"evidence:revision:"<tag-or-commit>"scan_report:"evidence/platform-coupling.txt"vectors:"evidence/baseline-vectors.json"next_check:"在目标 SDK 编译,确认对象布局改造范围"stop_if:"入口依赖无法替换的 Node.js 内置模块"这里的decision是当前证据下的工程选择,不是兼容性认证。后续编译或运行证据推翻假设时,应更新记录,而不是保住原结论。
把教学候选完整跑一遍
为了让筛选过程可以复查,我对本地教学夹具@demo/text-tool@1.0.0按相同步骤重新读数,而不是只给结论:
公开入口:Index.ets 核心源码:4 个 .ets 文件,共 97 行 直接依赖:0 DOM / Node.js 内置模块 / 动态执行命中:0 基础行为向量:3 组(正常、稳定、错误) 当前路线:进入 ArkTS 明确类型改造对应的复查命令如下;它们从候选根目录执行,退出码和命中内容要一起保存:
$source='.\src\main\ets'Get-ChildItem-LiteralPath$source-Recurse-Filter'*.ets'|Measure-Objectrg-n `-e'eval\s*\(|new\s+Function|\brequire\s*\('`-e'\bprocess\b|\bBuffer\b|\bwindow\b|\bdocument\b'`-e'from\s+["''](?:fs|path|http|https|crypto)["'']'`$sourcerg无输出时还要记录退出码;它只表示这些文本模式未命中,不证明不存在运行时耦合。接着人工读取Index.ets和四个实现文件,确认没有字符串拼接导入、代码生成或隐藏平台调用。
最终候选卡应给出一个明确判定:
| 判定项 | 本地夹具读回 | 决策影响 |
|---|---|---|
| 身份 | 本地教学夹具,版本1.0.0 | 只能演示方法,不能代表公开库 |
| 许可证 | 包字段与LICENSE均为 Apache-2.0 | 仍需实际项目按流程复核 |
| 规模 | 4 文件、97 行 | 适合第一次完整走通 |
| 平台命中 | 文本扫描 0,人工仍需读入口 | 暂不进入 Native 路线 |
| 行为基线 | 3 组确定输入输出 | 可以建立差分测试 |
| Go/No-Go | Go:进入第 7 篇源码侦察 | 编译失败时允许回退 |
这张表把“为什么继续”说清了;真实候选只要身份、许可证或停止条件有一项不清楚,就应判为 No-Go,而不是用总分掩盖硬风险。
真实公开候选卡:只做评估,不提前宣布兼容
为了避免整篇只围绕自建夹具,再选一个公开小库做同样的纸面筛选。这里使用escape-string-regexp@5.0.0,身份来自维护者仓库和包清单:包采用 MIT 许可证、生产依赖为 0、ESM 入口是index.js、类型入口是index.d.ts。上游实现文件只有 11 行,但包清单声明 Node.js>=12,因此仍不能直接推断可在 ArkTS/HarmonyOS 运行。
| 检查项 | 上游证据 | 初步结论 |
|---|---|---|
| 身份 | package.json固定版本 5.0.0 | 可以锁版本,后续还应固定 tag/commit |
| 许可证 | 包清单与仓库 License 均为 MIT | 许可证明确,仍需项目合规复核 |
| 生产依赖 | dependencies为空,发布文件仅入口与类型声明 | 依赖面小 |
| 公开 API | (string: string) => string | 输入输出容易建立向量 |
| 核心实现 | index.js做类型检查和两次正则替换 | 无文件、网络、DOM;需核对 ArkTS 正则与模块规则 |
| 停止条件 | 目标编译器不接受语法,或正则边界行为无法保持 | 立即停止“直接使用”,转源码改造或替代方案 |
最小上游行为向量可以从公开 README 和实现边界提取:
normal: "How much $ for a 🦄?" → "How much \\$ for a 🦄\\?" hyphen: "a-b" → "a\\x2db" error: non-string input → TypeError这一步得到的不是“推荐直接安装”,而是Go:进入源码侦察与目标 SDK 编译。只有第 7~10 篇完成入口、语法、行为向量和消费构建后,才有资格更新兼容结论。上游 README 还提示现代运行时已有RegExp.escape(),所以正式选型时要同时比较平台原生能力,避免维护一个不再必要的移植包。
常见失败:把包体积小当成适配简单
一个只有几十 KB 的包也可能在入口处访问process,或通过动态属性拼装对象。文件大小只说明传输量,不说明语言规则、运行时和许可证风险。正确做法是同时查看入口、依赖树、平台耦合和测试。
本篇产物与下一篇门槛
本篇产物是一张候选卡、一份初筛结果和三类测试向量。进入第 7 篇前,你应该能回答:候选的准确版本是什么、核心入口在哪里、有哪些平台耦合命中、为什么继续或停止。
官方来源
- 从 TypeScript 到 ArkTS 的适配规则:支持 ArkTS 对静态类型、对象布局、结构类型和模块语法有额外约束。访问日期:2026-10-18。
- ArkTS 迁移背景:用于解释为什么不能仅凭 TypeScript 可运行就推断 ArkTS 可编译。访问日期:2026-10-18。
- oh-package.json5:用于核对包名、版本、入口、许可证和依赖等模块级字段。访问日期:2026-10-18。
验证声明
本文于 2026-10-18 核对华为官方 ArkTS 迁移与oh-package.json5文档;对本地教学夹具运行了平台耦合文本扫描,结果为无命中,并沿用 HarmonyOS 6.0.2 Release(API 22)、ohpm 6.0.1、Hvigor 6.22.3 的独立实验工程。该夹具不是外部三方库,筛选结果只证明方法可复现,不构成真实开源库的许可证或兼容性结论;模拟器和真机未执行。