FlutterPatch:把 Shorebird 热更新的控制面搬回自己服务器

FlutterPatch:把 Shorebird 热更新的控制面搬回自己服务器

之前写过几篇 Shorebird 相关的东西,大概就是国内下载补丁、自己接 Appwrite 存补丁这些。后来又在项目里搞过 Petrel(雨燕)那套 Web 热更。

这篇文章说的是另一条线:Dart 代码还是走 Shorebird 那套补丁能力,但是检查补丁、存制品、发布回滚,全部放到自己服务器上。 我把这套东西叫 FlutterPatch。要用的话去官网下安装脚本,拿授权再装。网站在文末。


起因

Shorebird 本身能用。引擎和补丁格式不用我重新发明,冷启动之后 Dart 补丁就能生效,线上救急修 BUG 够用。

但是我们实际用下来,卡点往往不在「能不能打补丁」,而在:

  • 补丁检查和制品默认走官方云,内网 / 数据出域说不清楚
  • 有时候就想换张图、换点资源,不一定非要跟代码补丁绑死
  • 发补丁之前想先知道这次改动能不能热更,别打完才发现必须整包

所以 FlutterPatch 干的事情很窄:设备端继续用开源的 Shorebird updater,把 base_url 指到你自己部署的控制面。控制面负责 check、制品、后台、回滚这些。

不是 Fair / MXFlutter 那种动态化,也不是我之前研究过的 AST + DSL 无侵入那套。引擎和补丁格式我没去跟官方比快慢,那一层就是 Shorebird 的。真正比官方强的是控制面这一截,尤其是国内落地。


比官方强在哪

官方 Shorebird 的 Dart 补丁能力够用,这个我认。引擎和补丁格式没去比快慢。下面是实际用官方云觉得不够、后来自己补上的。

Shorebird 官方云 FlutterPatch
补丁检查 / 制品 api.shorebird.dev,补丁在官方侧 全部打你自己的 base_url,文件在本地盘或 MinIO
国内 / 内网 以前补丁在谷歌存储,国内最后一步经常下不下来;现在换了官方 CDN,数据和 check 还是他们的云 手机不访问官方 API,内网、等保、数据不出域能过
资源热更 主要修 Dart,换图基本还是发版 资源包单独下发,图片不用跟代码补丁绑死,往往不用等冷启动
能不能热更 打完补丁、真机不生效再查 check-ota 发版前对比基线,字体这类 unsupported 直接拦住,必须整包
国内落地方式 我 2023 年是向官方要地址,再把 dlc.vmcode 拷进沙盒改 patches_state.json,能验证,上不了生产 updater 认 base_url,协议还是 check / events,不用改沙盒
安装量 走官方账号和计费,安装量在他们那边 自搭建默认不按月安装量、月流量掐新补丁,授权看应用数和节点
Dart 补丁生效 冷启动 一样,冷启动,这点没吹
灰度 百分比放量 现在 check 不看百分比,用设备白名单先打测试机。适合内测,不是百分比的替代
引擎构建包 CDN Shorebird 官方源 现阶段还有可能用到官方源,补丁本身不走他们

整体是怎么串起来的

可以大概分成几块:

  • 手机上的 updater:还是 Shorebird 开源那套(shorebird_code_push
  • 控制面:检查该下哪个补丁、存文件、Dashboard、回滚(安装脚本部署)
  • CLI:flutterpatch,用来打 release / patch 并上传到控制面
  • 授权:装控制面的时候要带 license

设备侧配置差不多就这样:

yaml 复制代码
app_id: <uuid>
base_url: https://ota.你自己的域名
auto_update: true
# 生产建议再配 patch_public_key

App 起来之后大致流程是:

  1. POST {base_url}/api/v1/patches/check
  2. 控制面按 app、版本、平台、架构、channel 找最新且没回滚的补丁
  3. 返回带 HMAC 的下载地址和 hash
  4. 设备下载,下次冷启动生效
  5. POST /api/v1/patches/events 上报成功或失败

匹配规则没啥新鲜的,补丁号要比当前大才会下。回滚就是撤销发布,响应里会带需要卸掉的补丁号。下载地址有过期时间,不是永久裸链。

Dart 补丁是 Shorebird 的二进制 diff。native、插件、引擎换不了,这个之前写 Shorebird 的时候也说过,商店政策和技术边界都在这。


资源热更单独走

业务里经常出现「就换张活动图」。所以资源和代码补丁拆开了。

发版的时候先传一份资源快照(按应用、版本、平台)。后面热更发增减改清单,文件按 hash 存。设备另打:

text 复制代码
POST /api/v1/resources/check

再按 hash 拉内容。图片这类往往能比较快用上;Dart 补丁还是冷启动。

另外有个 check-ota。发版上传基线,打补丁前对比这次到底改了什么。碰到字体之类 unsupported 的变更,会直接告诉你必须整包发。这步挺实用,少打几次无效包。


灰度这块我说一下现状

以前内部留过百分比放量一类字段,现在设备 check 不看百分比。别被文档里的字段名带偏。

线上目前靠白名单:

  • 白名单关着:全量
  • 白名单开着,名单空的:谁都拿不到(适合先挂闸)
  • 白名单开着,名单里有设备 ID:只给这些人下
bash 复制代码
flutterpatch patch --whitelist --unique-ids=测试机1,测试机2

我们自己一般是先白名单几台真机,看着没问题再关。

部署也可以慢慢长。一开始 SQLite + 本地盘就能跑通;制品多了再上 MinIO;再往后 Postgres、Redis。没必要一上来按大厂拓扑抄。


怎么装、怎么打第一版补丁

从官网下载页拿安装脚本。先点接入,拿授权 ID,确认版本。然后:

bash 复制代码
# 本机装 CLI
chmod +x install_cli.sh
./install_cli.sh

# Windows
# .\install_cli.ps1

# 服务器装控制面
chmod +x install_remote.sh
./install_remote.sh --version <版本号> --license <授权ID>

装完会有 API 地址、Dashboard、Token。App 里加:

yaml 复制代码
dependencies:
  shorebird_code_push: ^2.0.3

shorebird.yamlbase_url 指到控制面。Android 模拟器访问电脑可以用 10.0.2.2,真机就局域网 IP 或者正式域名。

发版和打补丁大概这样:

bash 复制代码
export FLUTTERPATCH_TOKEN=<token>

flutterpatch init --base-url https://ota.example.com
flutterpatch release android --upload-baselines
flutterpatch check-ota --flutter . --android ./android --ios ./ios --version 1.0.0+1
flutterpatch patch --platforms=android --release-version=1.0.0+1 \
  --assets ./flutterpatch_assets.json \
  --baseline-assets ./flutterpatch_assets.prev.json

验证我们一般用 Build Marker:发版写一个标记,打补丁换另一个,真机杀进程再开,变了就算成。

iOS 必须真机。 模拟器跑 Shorebird patch 没用,这个坑以前踩过。

上线前 HTTPS、Token、补丁签名这些该开开。热更别拿去改 App 主用途,审核那关自己清楚。


不适合什么

想完全自研解释器、或者继续走我以前那套 AST/DSL 无侵入路线的,这不是同一条。

主做 Web 动态化的,可以看 Petrel 那套,跟 FlutterPatch 不是一个问题。

必须 OTA 改 native 插件的,做不到。

适合的大概是:Shorebird 的 Dart 补丁你认,但官方云过不了------数据要留在自己机器、国内要下得下来、资源要单独热更、发补丁前要先判断能不能 OTA。这几条是官方现在给不了、我们做这套就是为了补上的。


关于现状

前面 Shorebird 中国区、Appwrite 存补丁那些文章,可以当成这条路上更早的尝试;现在控制面是完整做下来的一版,安装脚本从官网走。

还有不少边边角角会继续改,比如百分比灰度目前就没用上,白名单先顶着。

想试用或者自搭建,去官网看一下,点「立即接入」联系我就行。备注掘金也行。

官网:www.flutterpatch.cn

相关推荐
用户2181697049305 小时前
Flutter tootip 轻量级提示
flutter
用户2181697049305 小时前
Flutter 拖拽 Draggable DragTarget
flutter
yume_sibai5 小时前
05-Flutter实战项目
前端·flutter
传奇开心果编程7 小时前
【Flutter入门练中学】第1课:从零开始
学习·flutter·ui
用户21816970493021 小时前
Flutter ClipPath
flutter
用户2181697049301 天前
Flutter 折叠组件 ExpansionTile ExpansionPanelList
flutter
不羁的木木2 天前
给鸿蒙 App 增加用系统应用打开文件的能力 —— open_app_file 的鸿蒙使用指南
flutter·harmonyos
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios